/
arti4
/
IndividualProject
Обзор
Документация
Войти
/
arti4
/
IndividualProject
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
MyGame/app/src/main/java/com/example/mygame/BackgroundLayer.java
311 строк
11 KB
arti4
upload files
18 ноя 2025, 12:41
18 ноя 2025, 12:41
f3a2f8a
Код
Авторство
О чём код?
package com.example.mygame; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Matrix; import android.content.Context; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class BackgroundLayer { private List<ParallaxLayer> layers; private int screenWidth, screenHeight; private Context context; private float baseSpeed; public BackgroundLayer(Context context, int screenWidth, int screenHeight, float baseSpeed) { this.context = context; this.screenWidth = screenWidth; this.screenHeight = screenHeight; this.baseSpeed = baseSpeed; initializeLayers(); } private void initializeLayers() { if (layers != null) { release(); } layers = new ArrayList<>(); float[] layerSpeeds = {0.05f, 0.2f, 0.4f, 0.6f, 0.8f}; Map<String, Bitmap> bitmapCache = new HashMap<>(); for (int i = 1; i <= 5; i++) { try { String layerName = "bg_layer" + i; int resourceId = context.getResources().getIdentifier(layerName, "drawable", context.getPackageName()); if (resourceId == 0) { continue; } String cacheKey = layerName + "_" + screenWidth + "_" + screenHeight; Bitmap stretchedBitmap = bitmapCache.get(cacheKey); Bitmap mirroredBitmap = bitmapCache.get(cacheKey + "_mirrored"); if (stretchedBitmap == null) { BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = calculateSampleSize(resourceId); options.inPreferredConfig = Bitmap.Config.RGB_565; Bitmap originalBitmap = BitmapFactory.decodeResource(context.getResources(), resourceId, options); if (originalBitmap == null) { continue; } int newWidth = calculateOptimalWidth(originalBitmap); stretchedBitmap = Bitmap.createScaledBitmap( originalBitmap, newWidth, screenHeight, true ); Matrix matrix = new Matrix(); matrix.preScale(-1, 1); mirroredBitmap = Bitmap.createBitmap( stretchedBitmap, 0, 0, stretchedBitmap.getWidth(), stretchedBitmap.getHeight(), matrix, true ); bitmapCache.put(cacheKey, stretchedBitmap); bitmapCache.put(cacheKey + "_mirrored", mirroredBitmap); if (originalBitmap != stretchedBitmap) { originalBitmap.recycle(); } } ParallaxLayer layer = new ParallaxLayer( stretchedBitmap, mirroredBitmap, layerSpeeds[i-1] * baseSpeed, i ); layers.add(layer); } catch (Exception e) { e.printStackTrace(); } } bitmapCache.clear(); } private int calculateSampleSize(int resourceId) { BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeResource(context.getResources(), resourceId, options); int imageHeight = options.outHeight; int imageWidth = options.outWidth; int scaleFactor = 1; if (imageHeight > screenHeight * 2 || imageWidth > screenWidth * 2) { scaleFactor = 2; } return scaleFactor; } private int calculateOptimalWidth(Bitmap originalBitmap) { float aspectRatio = (float) originalBitmap.getWidth() / originalBitmap.getHeight(); return (int) (screenHeight * aspectRatio); } public void update(float cameraX) { if (layers == null) return; for (ParallaxLayer layer : layers) { layer.update(); } for (ParallaxLayer layer : layers) { layer.checkAndRecycleTiles(); } } public void draw(Canvas canvas, float cameraX) { if (layers == null) return; for (ParallaxLayer layer : layers) { layer.draw(canvas, cameraX); } } public void setSpeed(float baseSpeed) { this.baseSpeed = baseSpeed; if (layers != null) { float[] layerSpeeds = {0.05f, 0.2f, 0.4f, 0.6f, 0.8f}; for (int i = 0; i < layers.size(); i++) { if (i < layerSpeeds.length) { layers.get(i).setSpeed(layerSpeeds[i] * baseSpeed); } } } } public void release() { if (layers != null) { for (ParallaxLayer layer : layers) { layer.release(); } layers.clear(); layers = null; } System.gc(); } private static class ParallaxLayer { private List<BackgroundTile> tiles; private Bitmap originalBitmap; private Bitmap mirroredBitmap; private float speed; private int layerNumber; private int screenWidth; public ParallaxLayer(Bitmap originalBitmap, Bitmap mirroredBitmap, float speed, int layerNumber) { this.originalBitmap = originalBitmap; this.mirroredBitmap = mirroredBitmap; this.speed = speed; this.layerNumber = layerNumber; this.screenWidth = originalBitmap.getWidth(); initializeTiles(); } private void initializeTiles() { tiles = new ArrayList<>(); if (originalBitmap == null) return; int tileWidth = originalBitmap.getWidth(); int tileHeight = originalBitmap.getHeight(); int tilesNeeded = 3; for (int i = 0; i < tilesNeeded; i++) { boolean isMirrored = (i % 2 != 0); Bitmap tileBitmap = isMirrored ? mirroredBitmap : originalBitmap; BackgroundTile tile = new BackgroundTile( tileBitmap, i * tileWidth, 0, tileWidth, tileHeight, speed, isMirrored ); tiles.add(tile); } } public void update() { if (tiles == null || tiles.isEmpty()) return; for (BackgroundTile tile : tiles) { tile.update(); } } public void checkAndRecycleTiles() { if (tiles.isEmpty()) return; BackgroundTile firstTile = tiles.get(0); int tileWidth = originalBitmap.getWidth(); if (firstTile.getRight() < -tileWidth) { tiles.remove(0); BackgroundTile lastTile = tiles.get(tiles.size() - 1); boolean isMirrored = !lastTile.isMirrored(); Bitmap tileBitmap = isMirrored ? mirroredBitmap : originalBitmap; BackgroundTile newTile = new BackgroundTile( tileBitmap, lastTile.getRight(), 0, tileWidth, originalBitmap.getHeight(), speed, isMirrored ); tiles.add(newTile); } } public void draw(Canvas canvas, float cameraX) { if (tiles == null) return; ensureEnoughTiles(cameraX); for (BackgroundTile tile : tiles) { tile.draw(canvas, cameraX); } } private void ensureEnoughTiles(float cameraX) { if (tiles.isEmpty()) { initializeTiles(); return; } BackgroundTile lastTile = tiles.get(tiles.size() - 1); int tileWidth = originalBitmap.getWidth(); while (lastTile.getRight() < cameraX + screenWidth + tileWidth) { boolean isMirrored = !lastTile.isMirrored(); Bitmap tileBitmap = isMirrored ? mirroredBitmap : originalBitmap; BackgroundTile newTile = new BackgroundTile( tileBitmap, lastTile.getRight(), 0, tileWidth, originalBitmap.getHeight(), speed, isMirrored ); tiles.add(newTile); lastTile = newTile; } } public void setSpeed(float speed) { this.speed = speed; if (tiles != null) { for (BackgroundTile tile : tiles) { tile.setSpeed(speed); } } } public void release() { if (originalBitmap != null) { originalBitmap.recycle(); } if (mirroredBitmap != null && mirroredBitmap != originalBitmap) { mirroredBitmap.recycle(); } if (tiles != null) { tiles.clear(); } } } private static class BackgroundTile { private Bitmap bitmap; private float x, y; private int width, height; private float speed; private boolean isMirrored; public BackgroundTile(Bitmap bitmap, float x, float y, int width, int height, float speed, boolean isMirrored) { this.bitmap = bitmap; this.x = x; this.y = y; this.width = width; this.height = height; this.speed = speed; this.isMirrored = isMirrored; } public void update() { x -= speed; } public void draw(Canvas canvas, float cameraX) { float drawX = x - cameraX; if (drawX + width > 0 && drawX < canvas.getWidth()) { canvas.drawBitmap(bitmap, drawX, y, null); } } public float getRight() { return x + width; } public boolean isMirrored() { return isMirrored; } public void setSpeed(float speed) { this.speed = speed; } } }