package org.dieubware.etts.model; import java.util.List; import org.dieubware.etts.Observable; import org.dieubware.etts.Observer; import org.dieubware.etts.Constants; import org.dieubware.etts.controller.ItemsObserver; import org.dieubware.etts.controller.ScoreObserver; import org.dieubware.etts.model.Items.ItemType; import com.badlogic.gdx.math.Intersector; import com.badlogic.gdx.math.Rectangle; public class GameModel extends Observable { private Player player; private Borders borders; private float velocityX, velocityY; private float gravity = -Constants.gravity; private float screenHeight, screenWidth; private boolean flap = true; private boolean lost = false; private ScoreManager scoreManager; private float lastBorderLeftY, lastBorderRightY; private float borderWidth = Constants.borderSize; private float playerWidth = Constants.playerSize; private Items items; private float lastItemY; private Difficulty difficulty; private float borderSize = Constants.borderSize; private List<Rectangle> bordersRight, bordersLeft; public enum Difficulty { NORMAL, HARD, INSANE, EASY } public GameModel(float screenHeight, float screenWidth) { player = new Player(0,0,playerWidth,playerWidth); borders = new Borders(); items = new Items(); this.screenHeight = screenHeight; this.screenWidth = screenWidth; init(); scoreManager = new ScoreManager(); setDifficulty(Difficulty.INSANE); } public void init() { player.pos(0, 0); borders.clear(); items.clear(); velocityX = -Constants.velocityX; } public void initBorders() { lastBorderRightY = 0; lastBorderLeftY = 0; float height = 3*Constants.textureSize + (int)((float)Math.random()*12f)*Constants.textureSize -1; borders.addBorder(player.x() - 5, lastBorderLeftY,borderSize, height, false); lastBorderLeftY += height; while(lastBorderRightY < screenHeight +100) { generateRightBorder(); } while(lastBorderLeftY < screenHeight +100) { generateLeftBorder(); } } public void movePlayer(float delta) { player.x(player.x() + velocityX*delta);// * time; // Apply horizontal velocity to X position if(player.y() < screenHeight/2 || velocityY < 0) { player.y(player.y() + velocityY*delta); //* time; // Apply vertical velocity to X position } else { borders.scroll(-velocityY*delta); items.scroll(-velocityY*delta); lastBorderLeftY -= velocityY*delta; lastBorderRightY -= velocityY*delta; lastItemY -= velocityY*delta; scoreManager.addScore((int)(velocityY*delta)); if(lastBorderLeftY < screenHeight +100) { generateLeftBorder(); } if(lastBorderRightY < screenHeight +100) { generateRightBorder(); } if(lastItemY < screenHeight +100) { generateItem(); } } velocityY += gravity*delta;// * time; if(isBouncing()) { System.out.println("Bounce"); velocityY *= -0.9f; } else if(player.y() < 0 || isBehindBorders()) setLost(true); checkItems(); } public void checkItems() { for(Item i : items) { if(Intersector.overlaps(i,player.getR())) { switch(i.getType()) { case KILL: setLost(true); break; case FLY: velocityY = Constants.velocityY*2f; /*if(velocityX >0) velocityX = Constants.velocityX; else velocityX = -Constants.velocityX;*/ break; } } } } public boolean isBehindBorders() { for(Integer i : borders.leftKeySet()) { Rectangle r = borders.get(i); if(player.y() > r.y && player.y() < (r.y + r.height) && player.x() < r.x) { return true; } } for(Integer i : borders.rightKeySet()) { Rectangle r = borders.get(i); if(player.y() > r.y && player.y() < (r.y + r.height) && player.x()+playerWidth > r.x + borderSize) { return true; } } return false; } public boolean isBouncing() { for(Integer i : borders.leftKeySet()) { Rectangle r = borders.get(i); if( //When the player jump into the border from below velocityY >= 0 //If falling, dies && player.y() + playerWidth >= r.y //is on border && player.y() + .75*playerWidth < r.y //Only a quarter of player is touching && player.x() + .25*playerWidth <= r.x //When the player lands on the border || velocityY <= 0 //If jumping, dies && player.y() <= r.y + r.height && player.y() + .25*playerWidth > r.y + r.height && player.x() + .25*playerWidth <= r.x) { //Down bounce return true; } } for(Integer i : borders.rightKeySet()) { Rectangle r = borders.get(i); if( //When the player jump into the border from below velocityY >= 0 //If falling, dies && player.y() + playerWidth >= r.y //is on border && player.y() + .75*playerWidth < r.y //Only a quarter of player is touching && player.x() + .75*playerWidth >= r.x + r.width //When the player lands on the border || velocityY <= 0 //If jumping, dies && player.y() <= r.y + r.height && player.y() + .25*playerWidth > r.y + r.height && player.x() + .75*playerWidth >= r.x + r.width) { //Down bounce return true; } } return false; } public void generateLeftBorder() { float height = 3*Constants.textureSize + (int)((float)Math.random()*12f)*Constants.textureSize -1; borders.addBorder( screenWidth/2 - Constants.insideBorder - (float)Math.random()*Constants.outsideBorder , lastBorderLeftY,borderSize, height, false); lastBorderLeftY += height; borders.clearRight(); } public void generateRightBorder() { float height = 3*Constants.textureSize + (int)((float)Math.random()*12f)*Constants.textureSize -1; //float height = 96+Constants.textureSize*(float)Math.random()*12.5f; borders.addBorder( screenWidth/2 + Constants.insideBorder + (float)Math.random()*Constants.outsideBorder , lastBorderRightY,borderSize, height, true); lastBorderRightY += height; borders.clearLeft(); } public void generateItem() { lastItemY = screenHeight*2 + (float)Math.random()*600f ; items.addItem( screenWidth/2 + (float)Math.random()*50f, lastItemY, Constants.playerSize*0.75f, Constants.playerSize*0.75f, ItemType.random()); items.clearOld(); } public void jump() { float dist = getBorderDist(); if(dist > 0 == velocityX > 0 && dist < 0 == velocityX < 0) { dist = Math.abs(dist); velocityY = Constants.velocityY ; velocityX *= -1; if(velocityX> 0) { player.setDirection(true); velocityX = Constants.velocityX-Constants.velocityX*(dist/borderSize); } else { player.setDirection(false); velocityX = (Constants.velocityX-Constants.velocityX*(dist/borderSize))*(-1); } flap = true; } else if(flap) { velocityY = Constants.velocityY; if(velocityX >0) velocityX = Constants.velocityX/2; else velocityX = -Constants.velocityX/2; flap = false; } } public float getBorderDist() { for(Integer i : borders.leftKeySet()) { if(Intersector.overlaps(borders.get(i), player.getR())) { return (player.x() - borders.get(i).x)*(-1); } } for(Integer i : borders.rightKeySet()) { if(Intersector.overlaps(borders.get(i), player.getR())) { return (borders.get(i).x + borders.get(i).width) - (player.x()+playerWidth) ; } } return 0; } public void setPlayerPos(float x, float y) { player.pos(x, y); } public void setPlayerObserver(Observer playerObserver) { player.addObserver(playerObserver); } public void setBordersObserver(Observer bordersObserver) { borders.addObserver(bordersObserver); } public void addItem(int x, int y, int width, int height, ItemType type) { items.addItem(x, y, width, height, type); } public void addBorder(int x, int y, int height, boolean right) { borders.addBorder(x, y, borderSize,height, right); } public boolean isLost() { return lost; } public void setLost(boolean b) { lost = b; setChanged(); notifyObservers(); } public void setDifficulty(Difficulty d) { this.difficulty = d; switch(d) { case EASY : borderSize = 2f*Constants.borderSize; break; case NORMAL: borderSize = 1.5f*Constants.borderSize; break; case HARD: borderSize = Constants.borderSize; break; case INSANE: borderSize = .5f*Constants.borderSize; break; } } public int getScore() { return scoreManager.getScore(); } public void resetScore() { scoreManager.resetScore(); } public void setScoreObserver(ScoreObserver scoreObserver) { scoreManager.addObserver(scoreObserver); } public void addItemObserver(ItemsObserver itemsObserver) { items.addObserver(itemsObserver); } public int getHighscore() { return scoreManager.getHighscore(); } public void saveScore() { if(scoreManager.isBeating()) { SaveManager.saveScore(scoreManager.getRawHighscore()); } } }