/
arti4
/
IndividualProject
Обзор
Документация
Войти
/
arti4
/
IndividualProject
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
MyGame/app/src/main/java/com/example/mygame/CarSelectionActivity.java
627 строк
25 KB
arti4
upload files
18 ноя 2025, 12:41
18 ноя 2025, 12:41
f3a2f8a
Код
Авторство
О чём код?
package com.example.mygame; import android.content.Context; import android.content.SharedPreferences; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.text.Spannable; import android.text.SpannableString; import android.text.style.ImageSpan; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager; import android.widget.Button; import android.widget.GridLayout; import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; import androidx.activity.OnBackPressedCallback; import androidx.appcompat.app.AppCompatActivity; import androidx.core.content.ContextCompat; public class CarSelectionActivity extends AppCompatActivity { private static final String PREF_NAME = "MotorcyclePrefs"; private static final String KEY_SELECTED_MOTORCYCLE = "selected_motorcycle"; private static final String KEY_UNLOCKED_MOTORCYCLES = "unlocked_motorcycles"; private int selectedMotorcycle = 0; private CompactMotorcyclePreview[] motorcyclePreviews; private int totalCrystals = 0; private int[] unlockPrices = {0, 50, 100, 150, 200, 250, 300, 350, 400, 450}; private BackgroundLayer backgroundLayer; private MenuBackgroundView backgroundView; private MenuThread menuThread; private float cameraX = 0f; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_car_selection); RelativeLayout rootLayout = findViewById(R.id.rootLayout); if (rootLayout != null) { backgroundView = new MenuBackgroundView(this); rootLayout.addView(backgroundView, 0); } loadSelectedMotorcycle(); loadCrystals(); setupMotorcycleGrid(); setupBackButton(); setupBackPressedHandler(); displayCrystals(); DisplayMetrics displayMetrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); int screenWidth = displayMetrics.widthPixels; int screenHeight = displayMetrics.heightPixels; backgroundLayer = new BackgroundLayer(this, screenWidth, screenHeight, 1.0f); if (backgroundView != null) { backgroundView.setBackgroundLayer(backgroundLayer); } } private void loadCrystals() { SharedPreferences prefs = getSharedPreferences("GamePrefs", Context.MODE_PRIVATE); totalCrystals = prefs.getInt("collected_crystals", 0); } private void displayCrystals() { TextView crystalsText = findViewById(R.id.crystalsText); if (crystalsText != null) { SpannableString spannable = new SpannableString(" " + totalCrystals); Drawable crystalDrawable = ContextCompat.getDrawable(this, R.drawable.ic_crystal); if (crystalDrawable != null) { crystalDrawable.setBounds(0, 0, dpToPx(20), dpToPx(20)); ImageSpan imageSpan = new ImageSpan(crystalDrawable, ImageSpan.ALIGN_BASELINE); spannable.setSpan(imageSpan, 0, 1, Spannable.SPAN_INCLUSIVE_EXCLUSIVE); } crystalsText.setText(spannable); } } private int dpToPx(int dp) { float density = getResources().getDisplayMetrics().density; return Math.round(dp * density); } private boolean isMotorcycleUnlocked(int motorcycleType) { SharedPreferences prefs = getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE); String unlockedString = prefs.getString(KEY_UNLOCKED_MOTORCYCLES, "0"); String[] unlockedArray = unlockedString.split(","); for (String unlocked : unlockedArray) { if (unlocked.equals(String.valueOf(motorcycleType))) { return true; } } return false; } private void unlockMotorcycle(int motorcycleType) { SharedPreferences prefs = getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE); String unlockedString = prefs.getString(KEY_UNLOCKED_MOTORCYCLES, "0"); if (!unlockedString.contains(String.valueOf(motorcycleType))) { unlockedString += "," + motorcycleType; prefs.edit().putString(KEY_UNLOCKED_MOTORCYCLES, unlockedString).apply(); } } private void purchaseMotorcycle(int motorcycleType) { int price = unlockPrices[motorcycleType]; if (totalCrystals >= price) { totalCrystals -= price; saveCrystals(); unlockMotorcycle(motorcycleType); selectMotorcycle(motorcycleType); displayCrystals(); setupMotorcycleGrid(); Toast.makeText(this, "Мотоцикл разблокирован!", Toast.LENGTH_SHORT).show(); } else { int needed = price - totalCrystals; Toast.makeText(this, "Недостаточно кристаллов! Нужно ещё: " + needed, Toast.LENGTH_LONG).show(); } } private void saveCrystals() { SharedPreferences prefs = getSharedPreferences("GamePrefs", Context.MODE_PRIVATE); prefs.edit().putInt("collected_crystals", totalCrystals).apply(); } @Override protected void onResume() { super.onResume(); startMenuAnimation(); } @Override protected void onPause() { super.onPause(); stopMenuAnimation(); } @Override protected void onDestroy() { super.onDestroy(); stopMenuAnimation(); if (backgroundLayer != null) { backgroundLayer.release(); } } private void startMenuAnimation() { if (menuThread == null) { menuThread = new MenuThread(); menuThread.setRunning(true); menuThread.start(); } } private void stopMenuAnimation() { if (menuThread != null) { menuThread.setRunning(false); menuThread = null; } } private void loadSelectedMotorcycle() { SharedPreferences prefs = getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE); selectedMotorcycle = prefs.getInt(KEY_SELECTED_MOTORCYCLE, 0); } private void saveSelectedMotorcycle() { SharedPreferences prefs = getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE); prefs.edit().putInt(KEY_SELECTED_MOTORCYCLE, selectedMotorcycle).apply(); } private class MenuThread extends Thread { private boolean running; private long lastTime = System.currentTimeMillis(); public void setRunning(boolean running) { this.running = running; } @Override public void run() { while (running) { long currentTime = System.currentTimeMillis(); long elapsedTime = currentTime - lastTime; cameraX += 0.5f; if (backgroundLayer != null) { backgroundLayer.update(cameraX); } runOnUiThread(new Runnable() { @Override public void run() { if (backgroundView != null) { backgroundView.setCameraX(cameraX); backgroundView.invalidate(); } } }); try { Thread.sleep(16); } catch (InterruptedException e) { e.printStackTrace(); } lastTime = currentTime; } } } private static class MenuBackgroundView extends View { private BackgroundLayer backgroundLayer; private float cameraX = 0f; public MenuBackgroundView(Context context) { super(context); } public MenuBackgroundView(Context context, AttributeSet attrs) { super(context, attrs); } public MenuBackgroundView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public void setBackgroundLayer(BackgroundLayer backgroundLayer) { this.backgroundLayer = backgroundLayer; } public void setCameraX(float cameraX) { this.cameraX = cameraX; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (backgroundLayer != null) { backgroundLayer.draw(canvas, cameraX); } } } private void setupMotorcycleGrid() { GridLayout gridLayout = findViewById(R.id.motorcycleGrid); gridLayout.removeAllViews(); gridLayout.setColumnCount(2); gridLayout.setRowCount(5); motorcyclePreviews = new CompactMotorcyclePreview[10]; String[] names = { "Спорт", "Гонка", "Эндуро", "Супер", "Неон", "Круизер", "Приключ", "Кафе", "Скрамб", "Чоппер" }; float[] speeds = {22.0f, 25.0f, 20.0f, 27.0f, 23.0f, 21.0f, 24.0f, 28.0f, 19.0f, 30.0f}; float[] powers = {70.0f, 85.0f, 60.0f, 90.0f, 75.0f, 65.0f, 80.0f, 95.0f, 55.0f, 100.0f}; for (int i = 0; i < 10; i++) { boolean unlocked = isMotorcycleUnlocked(i); CompactMotorcyclePreview preview = new CompactMotorcyclePreview(this, i, names[i], speeds[i], powers[i], unlocked, unlockPrices[i]); motorcyclePreviews[i] = preview; GridLayout.LayoutParams params = new GridLayout.LayoutParams(); params.width = 0; params.height = ViewGroup.LayoutParams.WRAP_CONTENT; params.columnSpec = GridLayout.spec(i % 2, 1f); params.rowSpec = GridLayout.spec(i / 2); params.setMargins(8, 8, 8, 8); preview.setLayoutParams(params); preview.setMotorcycleType(i); preview.setSelected(i == selectedMotorcycle); preview.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int type = ((CompactMotorcyclePreview) v).getMotorcycleType(); if (isMotorcycleUnlocked(type)) { selectMotorcycle(type); } else { purchaseMotorcycle(type); } } }); gridLayout.addView(preview); } updateMotorcycleInfo(); } private void selectMotorcycle(int type) { selectedMotorcycle = type; saveSelectedMotorcycle(); for (int i = 0; i < motorcyclePreviews.length; i++) { motorcyclePreviews[i].setSelected(i == type); } updateMotorcycleInfo(); } private void updateMotorcycleInfo() { TextView infoText = findViewById(R.id.motorcycleInfo); String[] fullNames = { "Спортивный", "Гоночный", "Эндуро", "Супербайк", "Неоновый", "Круизер", "Приключенческий", "Кафе-рейсер", "Скрамблер", "Чоппер" }; float[] speeds = {22.0f, 25.0f, 20.0f, 27.0f, 23.0f, 21.0f, 24.0f, 28.0f, 19.0f, 30.0f}; float[] powers = {70.0f, 85.0f, 60.0f, 90.0f, 75.0f, 65.0f, 80.0f, 95.0f, 55.0f, 100.0f}; float[] jumps = {1.2f, 1.4f, 1.0f, 1.5f, 1.3f, 1.1f, 1.35f, 1.6f, 0.9f, 1.7f}; String info = String.format( "%s | Скорость: %.1f | Мощность: %.0f | Прыжок: %.1f", fullNames[selectedMotorcycle], speeds[selectedMotorcycle], powers[selectedMotorcycle], jumps[selectedMotorcycle] ); infoText.setText(info); } private void setupBackButton() { Button backButton = findViewById(R.id.backButton); backButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { goBackToMainMenu(); } }); } private void setupBackPressedHandler() { getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) { @Override public void handleOnBackPressed() { goBackToMainMenu(); } }); } private void goBackToMainMenu() { finish(); overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out); } private static class CompactMotorcyclePreview extends View { private int motorcycleType; private String motorcycleName; private float motorcycleSpeed; private float motorcyclePower; private boolean isSelected; private boolean isUnlocked; private int unlockPrice; private Paint paint; private Bitmap motorcycleBitmap; private Paint lockPaint; private Paint pricePaint; private Bitmap lockBitmap; private Bitmap crystalBitmap; public CompactMotorcyclePreview(Context context, int type, String name, float speed, float power, boolean unlocked, int price) { super(context); this.motorcycleType = type; this.motorcycleName = name; this.motorcycleSpeed = speed; this.motorcyclePower = power; this.isUnlocked = unlocked; this.unlockPrice = price; this.paint = new Paint(); this.paint.setAntiAlias(true); this.lockPaint = new Paint(); this.lockPaint.setAntiAlias(true); this.lockPaint.setColor(Color.argb(180, 0, 0, 0)); this.pricePaint = new Paint(); this.pricePaint.setAntiAlias(true); this.pricePaint.setColor(Color.YELLOW); this.pricePaint.setTextSize(38f); this.pricePaint.setTextAlign(Paint.Align.CENTER); this.pricePaint.setShadowLayer(3, 1, 1, Color.BLACK); loadCrystalBitmap(context); loadLockBitmap(context); loadMotorcycleBitmap(context); setBackground(ContextCompat.getDrawable(context, R.drawable.compact_motorcycle_bg)); } private float getMotorcycleHeight() { switch (motorcycleType) { case 0: return dpToPx(108); case 1: return dpToPx(82); case 2: return dpToPx(101); case 3: return dpToPx(75); case 4: return dpToPx(75); case 5: return dpToPx(108); case 6: return dpToPx(108); case 7: return dpToPx(65); case 8: return dpToPx(84); case 9: return dpToPx(69); default: return dpToPx(88); } } private float getMotorcycleWidth() { switch (motorcycleType) { case 0: return dpToPx(150); case 1: return dpToPx(144); case 2: return dpToPx(163); case 3: return dpToPx(137); case 4: return dpToPx(157); case 5: return dpToPx(250); case 6: return dpToPx(230); case 7: return dpToPx(184); case 8: return dpToPx(236); case 9: return dpToPx(189); default: return dpToPx(150); } } private void loadLockBitmap(Context context) { try { android.graphics.drawable.Drawable lockDrawable = ContextCompat.getDrawable(context, R.drawable.ic_lock); if (lockDrawable != null) { int size = dpToPx(48); lockBitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(lockBitmap); lockDrawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); lockDrawable.draw(canvas); } } catch (Exception e) { e.printStackTrace(); lockBitmap = createFallbackLockBitmap(); } } private void loadCrystalBitmap(Context context) { try { int resourceId = context.getResources().getIdentifier("ic_crystal", "drawable", context.getPackageName()); if (resourceId != 0) { Bitmap originalBitmap = BitmapFactory.decodeResource(context.getResources(), resourceId); int size = dpToPx(36); crystalBitmap = Bitmap.createScaledBitmap(originalBitmap, size, size, true); } else { crystalBitmap = createFallbackCrystalBitmap(); } } catch (Exception e) { e.printStackTrace(); crystalBitmap = createFallbackCrystalBitmap(); } } private Bitmap createFallbackCrystalBitmap() { int size = dpToPx(36); Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); Paint paint = new Paint(); paint.setAntiAlias(true); float centerX = size / 2f; float centerY = size / 2f; float diamondSize = size * 0.7f; android.graphics.Path diamond = new android.graphics.Path(); diamond.moveTo(centerX, centerY - diamondSize/2); diamond.lineTo(centerX + diamondSize/2, centerY); diamond.lineTo(centerX, centerY + diamondSize/2); diamond.lineTo(centerX - diamondSize/2, centerY); diamond.close(); paint.setColor(Color.argb(255, 0, 200, 255)); paint.setStyle(Paint.Style.FILL); canvas.drawPath(diamond, paint); paint.setColor(Color.argb(255, 0, 150, 255)); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(2f); canvas.drawPath(diamond, paint); return bitmap; } private Bitmap createFallbackLockBitmap() { int size = dpToPx(48); Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); Paint lockPaint = new Paint(); lockPaint.setAntiAlias(true); lockPaint.setColor(Color.YELLOW); lockPaint.setStyle(Paint.Style.STROKE); lockPaint.setStrokeWidth(3f); float centerX = size / 2f; float centerY = size / 2f; float lockSize = size * 0.6f; canvas.drawCircle(centerX, centerY, lockSize / 2, lockPaint); lockPaint.setStyle(Paint.Style.FILL); canvas.drawCircle(centerX, centerY, lockSize * 0.15f, lockPaint); lockPaint.setStyle(Paint.Style.STROKE); lockPaint.setStrokeWidth(2f); canvas.drawLine(centerX, centerY - lockSize * 0.2f, centerX, centerY + lockSize * 0.2f, lockPaint); return bitmap; } private void loadMotorcycleBitmap(Context context) { try { int resourceId = context.getResources().getIdentifier( "car_" + (motorcycleType + 1), "drawable", context.getPackageName()); if (resourceId != 0) { motorcycleBitmap = BitmapFactory.decodeResource(context.getResources(), resourceId); } } catch (Exception e) { e.printStackTrace(); motorcycleBitmap = createFallbackBitmap(); } } private Bitmap createFallbackBitmap() { int width = (int) getMotorcycleWidth(); int height = (int) getMotorcycleHeight(); Bitmap bitmap = Bitmap.createBitmap(width *2, height, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); Paint fallbackPaint = new Paint(); fallbackPaint.setColor(Color.RED); canvas.drawRect(0, 0, width, height, fallbackPaint); fallbackPaint.setColor(Color.WHITE); fallbackPaint.setTextSize(20f); fallbackPaint.setTextAlign(Paint.Align.CENTER); canvas.drawText("MOTO " + (motorcycleType + 1), width / 2f, height / 2f, fallbackPaint); return bitmap; } public void setMotorcycleType(int type) { this.motorcycleType = type; invalidate(); } public int getMotorcycleType() { return motorcycleType; } public void setSelected(boolean selected) { this.isSelected = selected; invalidate(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int desiredWidth = dpToPx(150); int desiredHeight = dpToPx(100); setMeasuredDimension(desiredWidth, desiredHeight); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int width = getWidth(); int height = getHeight(); if (isSelected) { paint.setColor(Color.YELLOW); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(6f); canvas.drawRect(2, 2, width - 2, height - 2, paint); } if (motorcycleBitmap != null) { float motorcycleWidth = getMotorcycleWidth(); float motorcycleHeight = getMotorcycleHeight(); float motorcycleRatio = motorcycleWidth / motorcycleHeight; float maxDisplayWidth = width * 0.8f; float maxDisplayHeight = height * 0.6f; float displayRatio = maxDisplayWidth / maxDisplayHeight; int imageWidth, imageHeight; if (motorcycleRatio > displayRatio) { imageWidth = (int) maxDisplayWidth; imageHeight = (int) (imageWidth / motorcycleRatio); } else { imageHeight = (int) maxDisplayHeight; imageWidth = (int) (imageHeight * motorcycleRatio); } Bitmap scaledBitmap = Bitmap.createScaledBitmap(motorcycleBitmap, imageWidth, imageHeight, true); float left = (width - imageWidth) / 2f; float top = (height - imageHeight) / 2f; canvas.drawBitmap(scaledBitmap, left, top, paint); } if (!isUnlocked) { canvas.drawRect(0, 0, width, height, lockPaint); if (lockBitmap != null) { float lockLeft = (width - lockBitmap.getWidth()) / 2f; float lockTop = height * 0.3f - lockBitmap.getHeight() / 2f + dpToPx(10); canvas.drawBitmap(lockBitmap, lockLeft, lockTop, paint); } if (crystalBitmap != null) { float crystalLeft = (width - crystalBitmap.getWidth()) / 2f - dpToPx(15); float crystalTop = height * 0.75f - dpToPx(15); canvas.drawBitmap(crystalBitmap, crystalLeft, crystalTop, paint); pricePaint.setColor(Color.YELLOW); pricePaint.setTextSize(36f); String priceText = String.valueOf(unlockPrice); float textX = crystalLeft + crystalBitmap.getWidth() + dpToPx(20); float textY = crystalTop + crystalBitmap.getHeight() / 2 + dpToPx(5); canvas.drawText(priceText, textX, textY, pricePaint); } else { pricePaint.setColor(Color.YELLOW); pricePaint.setTextSize(36f); canvas.drawText(unlockPrice + " 💎", width / 2f, height * 0.85f, pricePaint); } } } private int dpToPx(int dp) { float density = getContext().getResources().getDisplayMetrics().density; return Math.round(dp * density); } } }