I have asked a similar question but i think i needed to be more clear on this.
Using Andriod and Open GL ES 2.0
This is my FrameTime Calculation
private long mCurrentTime = SystemClock.uptimeMillis()/1000; // set on entry to the render class
....
long mNewTime = SystemClock.uptimeMillis();
float FrameTime = (mNewTime - mCurrentTime)/ 1000.0f;
mCurrentTime = mNewTime;
To move my model i now say something like
Model.MoveX(PositionX += Speed * FrameTime);
This moves the model fine.
If i move between 3 points lets say -10, 0, 10 after couple of moves the model appears to be in the wrong position. if i increase the speed the error becomes more noticeable.
What cause this error and how can i fix it.
below is the function for moving the cube
private float MinCubeMovement = -10.0f;
private float MaxCubeMovement = 10.0f;
private float Middle = 0.0f;
private static boolean MoveLeftFlag = false;
private static boolean MoveRightFlag = false;
private int PositionFlag = 0;
....
private void UpdatePlayer(float FrameTime)
{
if(MoveLeftFlag == true)
{
if(PositionFlag == 0)
{
if(Cube1.PositionX >= MinCubeMovement)
{
Cube1.MoveLocalX(-CubeMoveSpeed * FrameTime );
}
else if(Cube1.PositionX <= MinCubeMovement)
{
PositionFlag = -1;
MoveLeftFlag = false;
}
}
if(PositionFlag == 1)
{
if(Cube1.PositionX >= Middle)
{
Cube1.MoveLocalX(-CubeMoveSpeed * FrameTime );
}
else if(Cube1.PositionX <= Middle)
{
MoveLeftFlag = false;
PositionFlag = 0;
}
}
}
if(MoveRightFlag == true)
{
if(PositionFlag == 0)
{
if(Cube1.PositionX <= MaxCubeMovement)
{
Cube1.MoveLocalX(CubeMoveSpeed * FrameTime );
}
else if(Cube1.PositionX >= MaxCubeMovement)
{
MoveRightFlag = false;
PositionFlag = 1;
}
}
if(PositionFlag == -1)
{
if(Cube1.PositionX <= Middle)
{
Cube1.MoveLocalX(CubeMoveSpeed * FrameTime );
}
else if(Cube1.PositionX >= Middle)
{
MoveRightFlag = false;
PositionFlag = 0;
}
}
}
}
MoveLocalX adds a float to the positionX in my model class, this works fine
Related
I am new to coding and don't really know what I am doing. I know that there my code is pretty inefficient and I could probably fix it later (i.e. collision and movement), but I have what I think is an efficient map setup. It only renders what is either around the camera or is around the player based on the camera type (freeRoam vs placerCentered). This works and runs fine until I start to resize pictures when I zoom in and out my map. I think that every time I draw a resized image my computer resizes it and then draws it for every instance of it rather than resizing it once and drawing it. Would I have to make images for every instance of zooming in or out or is there an optimized resizing tool that I am missing?
Google Drive link with images if anyone is interested: https://drive.google.com/drive/folders/1s5_9YPX7_6QWaxZPexN7pWk8zgmaT0w5?usp=sharing
(All images are 20 x 20 I think besides warrior1 and stoneTile1 which are both 32 x 32)
import processing.core.*;
import processing.event.MouseEvent;
import java.util.*;
public class Dungeon1 extends PApplet implements MyLibrary {
static gameState currentState;
static cameraState currentCameraState = cameraState.playerCentered;
enum gameState {
Over, Running
}
enum cameraState {
freeRoam, playerCentered
}
int cameraScaling = 20;
PImage testBoots;
PImage clown;
PImage testSquare;
PImage stoneTile1;
PImage resizedTile;
PImage warrior1;
float enemyX = 10;
float enemyY = 10;
float redSquare;
int currentXPos = 10;
int currentYPos = 10;
int tileType;
int mapWidth = 500;
int mapHeight = 500;
int[][] squareType = new int[mapHeight][mapWidth];
boolean movingUp, movingDown, movingLeft, movingRight;
int squareX;
int squareY;
boolean canMoveUp, canMoveDown, canMoveLeft, canMoveRight = true;
int cameraX = currentXPos;
int cameraY = currentYPos;
int lastCameraX;
int lastCameraY;
boolean centerCamera = false;
int pastMouseXPosition;
int pastMouseYPosition;
int squareWidth;
int squareHeight;
boolean mouseDragging = true, freeRoam, playerCentered;
public static void main(String[] args) {
PApplet.main("Dungeon1");
}
public void settings() {
fullScreen();
}
public void setup() {
playerStartPos();
createMap();
currentState = gameState.Running;
testBoots = loadImage("Images/TestBoots.png");
clown = loadImage("Images/clown.png");
testSquare = loadImage("Images/testSquare.png");
stoneTile1 = loadImage("Images/stoneTile1.png");
resizedTile = loadImage("Images/resizedTile.png");
warrior1 = loadImage("Images/warrior1.png");
}
public void draw() {
background(0, 0, 0);
drawMap();
isMoving();
}
public void keyPressed() {
if (key == 'w') {
movingUp = true;
}
if (key == 's') {
movingDown = true;
}
if (key == 'a') {
movingLeft = true;
}
if (key == 'd') {
movingRight = true;
}
if (key == 'k') {
Test = true;
}
if (key == 'c') {
currentCameraState = cameraState.playerCentered;
centerCamera = true;
}
if (key == 'v') {
currentCameraState = cameraState.freeRoam;
}
if (key == 'b') {
currentCameraState = cameraState.playerCentered;
}
}
public void keyReleased() {
if (key == 'w') {
movingUp = false;
}
if (key == 's') {
movingDown = false;
}
if (key == 'a') {
movingLeft = false;
}
if (key == 'd') {
movingRight = false;
}
if (key == 'k') {
Test = false;
}
}
public void mouseDragged(MouseEvent e) {
if (pastMouseXPosition < mouseX) {
lastCameraX--;
}
if (pastMouseXPosition > mouseX) {
lastCameraX++;
}
if (pastMouseYPosition < mouseY) {
lastCameraY--;
}
if (pastMouseYPosition > mouseY) {
lastCameraY++;
}
pastMouseXPosition = mouseX;
pastMouseYPosition = mouseY;
}
public void mousePressed() {
currentCameraState = cameraState.freeRoam;
mouseDragging = true;
pastMouseXPosition = mouseX;
pastMouseYPosition = mouseY;
}
public void mouseReleased() {
mouseDragging = false;
}
public void mouseWheel(MouseEvent e) {
if (e.getAmount() < 0) {
cameraScaling--;
} else {
cameraScaling++;
}
}
public void isMoving() {
if (movingUp) {
if (canMoveUp) {
currentYPos--;
cameraY--;
}
if (squareType[currentXPos][currentYPos] == 2) {
currentYPos++;
canMoveUp = false;
cameraY++;
}
}
if (movingDown) {
if (canMoveDown) {
currentYPos++;
cameraY++;
}
if (squareType[currentXPos][currentYPos] == 2) {
currentYPos--;
canMoveDown = false;
cameraY--;
}
}
if (movingRight) {
if (canMoveRight) {
currentXPos++;
cameraX++;
}
if (squareType[currentXPos][currentYPos] == 2) {
currentXPos--;
canMoveRight = false;
cameraX--;
}
}
if (movingLeft) {
if (canMoveLeft) {
currentXPos--;
cameraX--;
}
if (squareType[currentXPos][currentYPos] == 2) {
currentXPos++;
canMoveLeft = false;
cameraX++;
}
}
if (squareType[currentXPos][currentYPos] != 2) {
drawPlayer();
canMoveUp = true;
canMoveLeft = true;
canMoveDown = true;
canMoveRight = true;
}
}
public void playerStartPos() {
currentXPos = 96/2;
currentYPos = 54/2;
}
public void drawPlayer() {
if (currentCameraState == cameraState.playerCentered) {
image(testSquare, (currentXPos * cameraScaling - cameraX * cameraScaling), (currentYPos * cameraScaling - cameraY * cameraScaling), cameraScaling, cameraScaling);
} else if (currentCameraState == cameraState.freeRoam) {
image(testSquare, (currentXPos * cameraScaling - lastCameraX * cameraScaling), (currentYPos * cameraScaling - lastCameraY * cameraScaling), cameraScaling, cameraScaling);
}
}
public void createMap() {
//First creates the plane to navigate
for (int r = 0; r < mapHeight; r++) {
for (int c = 0; c < mapWidth; c++) {
redSquare = generator.nextInt(100);
if (redSquare > 90) {
tileType = 2;
} else {
tileType = 0;
}
squareType[r][c] = tileType;
}
}
}
public void drawMap() {
//TODO: Either figure out how to make actual scaled images not run poorly or make a bunch of images that only are displayed a scaled resolution
if (cameraScaling < 15) {
cameraScaling = 15;
}
if (cameraScaling > 50) {
cameraScaling = 50;
}
if (centerCamera) {
cameraX = currentXPos - 47*20/ cameraScaling;
cameraY = currentYPos - 23*20/ cameraScaling;
}
squareWidth = 20+ cameraScaling;
squareHeight = 20+ cameraScaling;
centerCamera = false;
if (currentCameraState == cameraState.freeRoam) {
cameraX = lastCameraX;
cameraY = lastCameraY;
for (int r = lastCameraX; r < lastCameraX + 96*20/ cameraScaling + 2 ; r++) {
for (int c = lastCameraY; c < lastCameraY + 54*20/ cameraScaling + 2; c++) {
squareX = r * cameraScaling - lastCameraX * cameraScaling;
squareY = c * cameraScaling - lastCameraY * cameraScaling;
if (r > 0 && c > 0 && r < mapWidth && c < mapHeight) {
if (squareType[r][c] == 0) {
image(resizedTile, squareX, squareY, cameraScaling, cameraScaling);
} else {
colorTiles(r, c);
rect(squareX, squareY, cameraScaling, cameraScaling);
}
}
}
}
} else if (currentCameraState == cameraState.playerCentered) {
lastCameraX = cameraX;
lastCameraY = cameraY;
for (int r = cameraX; r < cameraX + 96*20/ cameraScaling + 2; r++) {
for (int c = cameraY; c < cameraY + 54*20/ cameraScaling + 2; c++) {
squareX = r * cameraScaling - cameraX * cameraScaling;
squareY = c * cameraScaling - cameraY * cameraScaling;
if (r > 0 && c > 0 && r < mapWidth && c < mapHeight) {
if (squareType[r][c] == 0) {
image(resizedTile, squareX, squareY, cameraScaling, cameraScaling);
} else {
colorTiles(r, c);
rect(squareX, squareY, cameraScaling, cameraScaling);
}
}
}
}
}
}
public void colorTiles(int r, int c) {
if (squareType[r][c] == 2) {
fill(255, 0, 0);
}
}
}```
I have been working on a game for a while and I would like to have a different class for each type of Creature that there is. Right now, all of the different creatures' AI is run in a long switch and I would like a superclass to ovveride that function with that AI for that creature. I have this set up but it won't override.
Am I forgetting something?
Bunny.java:
package creature;
import org.newdawn.slick.opengl.Texture;
import creature.Creature;
import creature.CreatureType;
import data.Tile;
public class Bunny extends Creature{
public Bunny(CreatureType type, float x, float y, float speed1) {
super(type, x, y, speed1);
}
public void AI(int type) {
System.out.println("test");
}
}
Creature.java:
public Creature(CreatureType type, float x, float y, float speed1) {
this.texture = drawImg(type.textureName);
this.textureHamster = drawImg("creatures/HamsterFace");
this.healthBackground = drawImg("health_background");
this.healthForeground = drawImg("health_foreground");
this.healthBorder = drawImg("health_border");
this.startTile = startTile;
this.x = x;
this.y = y;
this.intX = (int) x;
this.intY = (int) y;
this.width = texture.getImageWidth();
this.height = texture.getImageHeight();
this.speed1 = speed1;
this.speed = speed;
this.intspeed = speed;
this.grid = grid;
this.health = type.health;
this.inithealth = type.health;
this.hiddenHealth = health;
this.startHealth = health;
this.dir = false;
this.dchosen = false;
this.setx = 0;
this.hurt = 0;
this.panick = 0;
this.deathWish = 0;
this.pdir = -1;
this.myX = x;
this.myY = HEIGHT / 2;
this.right = false;
this.left = false;
this.fade = 0;
this.fir = true;
this.aiType = type.aiType;
this.yOffset = 0;
}
.....
public void AI(int type) {
if(panic > 0)
panic--;
hurt();
speed = speed1;
switch(type) {
case 1:
if(panic > 0) {
if(pickRandom(150, 300) < 10) {
direction = !direction;
}
if(direction) {
if(!right) {
x += speed;
} else {
if(falling < 2)
gravity = 8;
}
} else {
if(!left) {
x -= speed;
} else {
if(falling < 2)
gravity = 8;
}
}
} else {
if(getRange(WIDTH / 2, myX) > 200) {
directionCoolDown++;
if(directionCoolDown > pickRandom(150, 3000)) {
direction = !direction;
directionCoolDown = 0;
}
if(direction) {
if(!right) {
x += speed / 3.2;
} else {
if(falling < 2)
gravity = 8;
}
} else {
if(!left) {
x -= speed / 3.2;
} else {
if(falling < 2)
gravity = 8;
}
}
} else {
if(myX < WIDTH / 2) {
direction = true;
} else {
direction = false;
}
}
}
break;
case 2:
yOffset = -25;
if(!angry) {
pdir = 0;
if(getRange(Player.getX(), myX) < 300) {
hamsterFace = true;
} else {
hamsterFace = false;
}
if(!hamsterFace) {
directionCoolDown++;
if(directionCoolDown > pickRandom(150, 3000)) {
direction = !direction;
directionCoolDown = 0;
}
if(direction) {
if(!right) {
x += speed / 3.2;
} else {
if(falling < 2)
gravity = 8;
}
} else {
if(!left) {
x -= speed / 3.2;
} else {
if(falling < 2)
gravity = 8;
}
}
}
} else {
pdir++;
hamsterFace = false;
if(myX < Player.getX()) {
direction = true;
} else {
direction = false;
}
if(direction) {
if(!right) {
x += speed / 1;
} else {
if(falling < 2)
gravity = 8;
}
} else {
if(!left) {
x -= speed / 1;
} else {
if(falling < 2)
gravity = 8;
}
}
if(getRange(myX, Player.getX()) < 5 && getRange(myY, Player.getY()) < 5) {
hurtPlayer(-2);
direction = !direction;
if(direction) {
if(!right) {
x += speed * 10;
} else {
if(falling < 2)
gravity = 8;
}
} else {
if(!left) {
x -= speed * 10;
} else {
if(falling < 2)
gravity = 8;
}
}
}
}
if(panic > 1) {
angry = true;
} else {
if(pdir > pickRandom(1000,2000)) {
angry = false;
}
}
break;
}
}
.....
(Both classes are in the same package)
EDIT: I fixed the typo....
you have in the Bunny class:
public void AI() {
System.out.println("test");
}
in the Creature class:
public void AI(int type) {
if(panic > 0)
....
so
void AI(int type) and void AI() are NOT the same method (check the signature and how they take different parameters!)
therefore the Bunny class is not overriding anything from the parent class
--
edit:
now that your classes have a method void AI(int type) then we can say that
Bunny override the Creature AI method and everytime you call bunny.AI(f) your bunny method will be called!
Im creating a game. I need to create objects randomly but i want them to come in a certain number. Here is my main class code for randomly created object
private void randomTiles() {
int randomXtile = new Random().nextInt(9500) + 20;
int randomYtile = new Random().nextInt(12) + 0;
Tile t = new Tile(randomXtile, randomYtile, 3);
tilearray.add(t);
}
private void updateTiles() {
randomTiles();
for (int i = 0; i < tilearray.size(); i++) {
Tile t = (Tile) tilearray.get(i);
t.update();
}
}
private void paintTiles(Graphics g) {
for (int i = 0; i < tilearray.size(); i++) {
Tile t = (Tile) tilearray.get(i);
g.drawImage(t.getTileImage(), t.getTileX(), t.getTileY(), this);
}
}
tile constructor is
public Tile(int x, int y, int typeInt) {
tileX = x * 40;
tileY = y * 40;
type = typeInt;
r = new Rectangle();
if (type == 5) {
tileImage = StartingClass.tiledirt;
} else if (type == 8) {
tileImage = StartingClass.tilegrassTop;
} else if (type == 4) {
tileImage = StartingClass.tilegrassLeft;
} else if (type == 6) {
tileImage = StartingClass.tilegrassRight;
} else if (type == 2) {
tileImage = StartingClass.tilegrassBot;
} else if (type == 3) {
tileImage = StartingClass.ice;
hp = 2;
} else {
type = 0;
}
}
and somewhere in my game object should come at certain coordinates. Can you help me about this ?
I am currently developing an android game using LibGdx. I am trying to get the multi touch functionality working as the game requires the player to have one thumb to control the character and the other to click buttons.
Code:
for (int i = 0; i < 2; i++) {
if (Gdx.input.isTouched(i)) {
final int iX = Gdx.input.getX(i);
if (iX > screenwidth - screenwidth / 14) {
buttontouch = true;
} else {
buttontouch = false;
}
if (iX <= screenwidth - screenwidth / 14) {
playertouch = true;
}else{
playertouch = false;
}
}
}
if (playertouch){
etc...
}
if(buttontouch){
etc...
}
The player can be moved and the buttons pressed, but not at the same time :( ... which is what i need.
Any help would be greatly appreciated! Thanks in advance.
Logic which moves your character should be called inside for circle. You should move your character every circle iteration (if button was clicked) Like this:
for (int i = 0; i < 2; i++) {
if (Gdx.input.isTouched(i)) {
final int iX = Gdx.input.getX(i);
if (iX > screenwidth - screenwidth / 14) {
buttontouch = true;
} else {
buttontouch = false;
}
if (iX <= screenwidth - screenwidth / 14) {
playertouch = true;
}else{
playertouch = false;
}
}
//Logic here!
if (playertouch){
etc...
}
if(buttontouch){
etc...
}
}
Ok I seemed to have worked out an answer.
added
if (Gdx.input.isTouched(i)) {
below in each boolean if
for (int i = 0; i < 2; i++) {
if (Gdx.input.isTouched(i)){
final int iX = Gdx.input.getX(i);
if (iX > screenwidth - screenwidth / 14) {
buttontouch = true;
} else {
buttontouch = false;
}
if (iX <= screenwidth - screenwidth / 14) {
playertouch = true;
}else{
playertouch = false;
}
}
}
//Logic here!
if (playertouch){
if (Gdx.input.isTouched(i)) {
etc...
}
}
if(buttontouch){
if (Gdx.input.isTouched(i)) {
etc...
}
}
}
I am writing an Android game right now and I would need some help in the collision of the wall on screen. When I drag the ball in the top and right it able to collide in wall but when I drag it faster it was able to overlap in the wall
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()) {
// if the player moves
case MotionEvent.ACTION_MOVE: {
if (playerTouchRect.contains(x, y)) {
boolean left = false;
boolean right = false;
boolean up = false;
boolean down = false;
boolean canMove = false;
boolean foundFinish = false;
if (x != pLastXPos) {
if (x < pLastXPos) {
left = true;
} else {
right = true;
}
pLastXPos = x;
}
if (y != pLastYPos) {
if (y < pLastYPos) {
up = true;
} else {
down = true;
}
pLastYPos = y;
}
plCellRect = getRectFromPos(x, y);
newplRect.set(playerRect);
newplRect.left = x - (int) (playerRect.width() / 2);
newplRect.right = x + (int) (playerRect.width() / 2);
newplRect.top = y - (int) (playerRect.height() / 2);
newplRect.bottom = y + (int) (playerRect.height() / 2);
int currentRow = 0;
int currentCol = 0;
currentRow = getRowFromYPos(newplRect.top);
currentCol = getColFromXPos(newplRect.right);
if(!canMove){
canMove = mapManager.getCurrentTile().pMaze[currentRow][currentCol] == Cell.wall;
canMove =true;
}
finishTest = mapManager.getCurrentTile().pMaze[currentRow][currentCol];
foundA = finishTest == Cell.valueOf(letterNotGet + "");
canMove = mapManager.getCurrentTile().pMaze[currentRow][currentCol] != Cell.wall;
canMove = (finishTest == Cell.floor || finishTest == Cell.pl) && canMove;
if (canMove) {
invalidate();
setTitle();
}
if (foundA) {
mapManager.getCurrentTile().pMaze[currentRow][currentCol] = Cell.floor;
// finishTest
letterGotten.add(letterNotGet);
playCurrentLetter();
/*sounds.play(sExplosion, 1.0f, 1.0f, 0, 0, 1.5f);*/
foundS = letterNotGet == 's';
letterNotGet++;
}if(foundS){
AlertDialog.Builder builder = new AlertDialog.Builder(mainActivity);
builder.setTitle(mainActivity.getText(R.string.finished_title));
LayoutInflater inflater = mainActivity.getLayoutInflater();
View view = inflater.inflate(R.layout.finish, null);
builder.setView(view);
View closeButton =view.findViewById(R.id.closeGame);
closeButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View clicked) {
if(clicked.getId() == R.id.closeGame) {
mainActivity.finish();
}
}
});
AlertDialog finishDialog = builder.create();
finishDialog.show();
}
else {
Log.d(TAG, "INFO: updated player position");
playerRect.set(newplRect);
setTouchZone();
updatePlayerCell();
}
} // end of (CASE) if playerTouch
break;
} // end of (SWITCH) Case motion
}//end of Switch
return true;
}//end of TouchEvent
private void finish() {
// TODO Auto-generated method stub
}
public int getColFromXPos(int xPos) {
val = xPos / (pvWidth / mapManager.getCurrentTile().pCols);
if (val == mapManager.getCurrentTile().pCols) {
val = mapManager.getCurrentTile().pCols - 1;
}
return val;
}
/**
* Given a y pixel position, return the row of the cell it is in This is
* used when determining the type of adjacent Cells.
*
* #param yPos
* y position in pixels
* #return The cell this position is in
*/
public int getRowFromYPos(int yPos) {
val = yPos / (pvHeight / mapManager.getCurrentTile().pRows);
if (val == mapManager.getCurrentTile().pRows) {
val = mapManager.getCurrentTile().pRows - 1;
}
return val;
}
/**
* When preserving the position we need to know which cell the player is in,
* so calculate it from the centre on its Rect
*/
public void updatePlayerCell() {
plCell.x = (playerRect.left + (playerRect.width() / 2))
/ (pvWidth / mapManager.getCurrentTile().pCols);
plCell.y = (playerRect.top + (playerRect.height() / 2))
/ (pvHeight / mapManager.getCurrentTile().pRows);
if (mapManager.getCurrentTile().pMaze[plCell.y][plCell.x] == Cell.floor) {
for (int row = 0; row < mapManager.getCurrentTile().pRows; row++) {
for (int col = 0; col < mapManager.getCurrentTile().pCols; col++) {
if (mapManager.getCurrentTile().pMaze[row][col] == Cell.pl) {
mapManager.getCurrentTile().pMaze[row][col] = Cell.floor;
break;
}
}
}
mapManager.getCurrentTile().pMaze[plCell.y][plCell.x] = Cell.pl;
}
}
public Rect getRectFromPos(int x, int y) {
calcCell.left = ((x / cellWidth) + 0) * cellWidth;
calcCell.right = calcCell.left + cellWidth;
calcCell.top = ((y / cellHeight) + 0) * cellHeight;
calcCell.bottom = calcCell.top + cellHeight;
Log.d(TAG, "Rect: " + calcCell + " Player: " + playerRect);
return calcCell;
}
public void setPlayerRect(Rect newplRect) {
playerRect.set(newplRect);
}
private void setTouchZone() {
playerTouchRect.set(
playerRect.left - playerRect.width() / TOUCH_ZONE,
playerRect.top - playerRect.height() / TOUCH_ZONE,
playerRect.right + playerRect.width() / TOUCH_ZONE,
playerRect.bottom + playerRect.height() / TOUCH_ZONE);
}
public Rect getPlayerRect() {
return playerRect;
}
public Point getPlayerCell() {
return plCell;
}
public void setPlayerCell(Point cell) {
plCell = cell;
}
}*
This is an architectural problem. You can read more about it here.
In essence, your physics simulation (as simple as might be) is coupled to your framerate (which is capped at 60fps). Any events occurring faster than 60Hz cannot be processed accurately hence your bug.
The solution is to run the collision detection on an independent thread and draw the state it calculates at 60fps.
Also, take a look at these gamedev questions that refer to the same article.