I'm having a problem getting the screen to change to the image I want to display.
The image is a spritesheet which is set up as an array ( ie first screen is in array index 0 etc...)
I can change when I press the UP key and LEFT key and ENTER key, but the program will not display the correct image pressing the DOWN key.
I eventually want to discard the arrow key presses and subsituite them for numbers (the phone number keys ) 4 to return, 1,2,3 to go to certain pages and enter to go to the next page, if there is more information on a particular page.
private void actOnKeyStates(int k) {
if ((k & DOWN) != 0) {
Title = false;
HowToPlay = true;
Controls = false;
About = false;
}
if ((k & UP) != 0) {
Title = false;
HowToPlay = false;
Controls = true;
About = false;
}
if ((k & LEFT) != 0) {
Title = true;
HowToPlay = false;
Controls = false;
About = false;
}
if ((k & FIRE_PRESSED) != 0) {
Title = false;
HowToPlay = false;
Controls = false;
About = true;
}
update();
}
public void update() {
if (Title) {
Screen.setFrame(0);
}
if (HowToPlay) {
Screen.setFrame(1);
}
if (Controls) {
Screen.setFrame(4);
}
if (About) {
Screen.setFrame(5);
}
}
I would appreciate any advice on the matter.
First I think it would be better if you established a state for your game, rather than just using an increasing number of boolean values. Such as this:
public enum ScreenState { Title, HowToPlay, Controls, About }
private ScreenState currentScreen = ScreenState.Title;
private void actOnKeyStates(int k) {
if ((k & DOWN) != 0) {
currentScreen = ScreenState.HowToPlay;
}
if ((k & UP) != 0) {
currentScreen = ScreenState.Controls;
}
if ((k & LEFT) != 0) {
currentScreen = ScreenState.Title;
}
if ((k & FIRE_PRESSED) != 0) {
currentScreen = ScreenState.About;
}
update();
}
public void update() {
switch(currentScreen) {
case Title:
Screen.setFrame(0);
break;
case HowToPlay:
Screen.setFrame(1);
break;
case Controls:
Screen.setFrame(4);
break;
case About:
Screen.setFrame(5);
break;
}
}
The second thing you need to do is confirm that k & DOWN is being executed correctly when the DOWN arrow is pressed. Also confirm that the image you are looking for is correctly placed in the position 1 in your sprite sheet.
Related
So we recently started coding in college and I'm having trouble with my game in Greenfoot. I should normally be able to collect 5 coins on level 1, go to the door, and progress to level 2 and so on... This is my piece of code so far:
private void collect () {
Actor coin = getOneIntersectingObject(Coin.class);
if (coin != null) {
getWorld().removeObject(coin);
coinsCollected++;
}
if (coinsCollected == 5 && fiveCoinsLevel1 == false) {
if (this.getWorld().getClass() == Level_1.class) {
getWorld().addObject(new door_temp(), 157, 162);
fiveCoinsLevel1 = true;
secondLevel();
coinsCollected = 0;
}
}
if (coinsCollected == 5 && fiveCoinsLevel2 == false && fiveCoinsLevel1 == true) {
if (this.getWorld().getClass() == Level_2.class) {
getWorld().addObject(new door_temp(), 157, 162);
fiveCoinsLevel2 = true;
thirdLevel();
}
}
}
After that I have two methods that set the world to either level 2 or 3:
public void secondLevel () {
Actor secondlvl = getOneIntersectingObject(door_temp.class);
if (secondlvl != null) {
Greenfoot.setWorld(new Level_2());
}
}
public void thirdLevel () {
Actor thirdlvl = getOneIntersectingObject(door_temp.class);
if (thirdlvl != null) {
Greenfoot.setWorld(new Level_3());
}
}
Now for some reason, once I collect all 5 coins on level 1 and reach the door to go to level 2, it sends me straight to level 3.
Thanks to anyone who can help me :)
I'm creating a small application where a user can take a Box and arrange it on a Pallet. I've managed to get it working using a 50x100 Box and making it snap to a grid by rounding the mouse position to the closest 50 value.
The problem is that when I use an odd sized Box, e.g. 50x110, the boxes will overlap or have gaps, since I am forcing them to move to the closest 50 value. If I increase this value I get gaps between the boxes and if I make it too small, it becomes hard for a user to align the boxes so there is no gap between them
I was wondering if anyone had anyway to approach this problem of getting the boxes to snap/align themselves with each other regardless of the size and ratio?
Here is part of the code that generates and places the buttons onto the pallet, explanation of the missing functions at the bottom
int package_width = 60;
int package_height = 100;
int snap_size = 50; //snap everything into 5 pixel limits
int count = 0;
int pallet_width = 400;
int pallet_height = 400;
JButton package_left = new JButton("<");
package_left.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
Selector.selected = "<";
}
});
JPanel pallet = new JPanel();
pallet.setLayout(null);
pallet.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
if(Selector.selected != "" && Selector.selected != null) {
Point position = e.getPoint();
JButton pack = new JButton(Selector.selected + Selector.count);
int x_pos = -1;
int y_pos = -1;
int pack_height = -1;
int pack_width = -1;
if(Selector.selected == "<" || Selector.selected == ">") {
pack_width = package_height;
pack_height = package_width;
}else {
pack_width = package_width;
pack_height = package_height;
}
pack.setSize(pack_width, pack_height);
//snap using the height and width
x_pos = (int)((int)(position.x-pack_width/2)/(pack_width/2))*pack_width/2;
y_pos = (int)((int)(position.y-pack_height/2)/(pack_height/2))*pack_height/2;
pack.setLocation(x_pos, y_pos);
if(collision(pack.getLocation(), snap_size)) {
x_pos = -1;
y_pos = -1;
}
//If the position failed to set, its overlapping
if (x_pos != -1 && y_pos != -1) {
Selector.point_list.add(pack.getLocation());
if(Selector.selected == "<" || Selector.selected == ">") {
Selector.point_list.add(new Point(pack.getLocation().x+snap_size, pack.getLocation().y));
}else{
Selector.point_list.add(new Point(pack.getLocation().x, pack.getLocation().y+snap_size));
}
pallet.add(pack);
main_page.repaint();
Selector.selected = "";
}
}
}
}
Collision Function
public static boolean collision(Point pack, int snap_size) {
Iterator<Point> it = Selector.point_list.iterator();
Point next;
while(it.hasNext()) {
next = it.next();
if(pack.x == next.x && pack.y == next.y) {
return true;
}
if(Selector.selected == "<" || Selector.selected == ">") {
if(pack.x+snap_size == next.x && pack.y == next.y) {
return true;
}
}else {
if(pack.x == next.x && pack.y+snap_size == next.y) {
return true;
}
}
}
return false;
}
The class Selector holds 2 static variables. One is the point_list which holds a list of all the points that have a button in them already. The other is selected which is used to determine the orientation of the button based on if the first button pressed has ^,v,< or > on it.
I recently had to code up an interpreter for Bitcoin's script language; part of this involved coming up with an algorithm to check that the control flow in a given script made sense (i.e. every OP_IF had a matching OP_ENDIF, every OP_ELSE and OP_ENDIF had a matching OP_IF, etc.).
This is what I came up with:
public class if_else_checker {
public static boolean search(String[] commands, String[] tracker, int if_index) {
boolean seenElse = false;
for (int i = if_index; i < commands.length; i++) {
if (commands[i].equals("OP_ELSE")) {
if (seenElse == true && tracker[i] == null) return false;
if (tracker[i] == null) {
tracker[i] = "OP_ELSE";
seenElse = true;
}
}
else if (commands[i].equals("OP_ENDIF")) {
if (tracker[i] != null && tracker[i].equals("OP_ENDIF"))
{
continue;
}
tracker[i] = "OP_ENDIF";
return true;
}
else if (commands[i].equals("OP_IF")) {
if (tracker[i] != null && tracker[i].equals("OP_IF")) {
continue;
}
tracker[i] = "OP_IF";
if (search(commands, tracker, i + 1) == false) return false;
}
}
return false;
}
public static boolean validate(String[] args)
{
String[] tracker = new String[args.length];
for (int i = 0; i < args.length; i++)
{
if (args[i].equals("OP_IF"))
{
if (tracker[i] == null || !tracker[i].equals("OP_IF"))
{
tracker[i] = "OP_IF";
if (search(args, tracker, i + 1) == false) return false;
}
else continue;
}
else if (args[i].equals("OP_ELSE"))
{
if (tracker[i] == null || !tracker[i].equals("OP_ELSE")) return false;
}
else if (args[i].equals("OP_ENDIF"))
{
if (tracker[i] == null || !tracker[i].equals("OP_ENDIF")) return false;
}
}
return true;
}
public static void main(String[] args)
{
System.out.println(validate(args));
}
}
It works, but I was wondering if there is a way to optimise it/if there is a standard way of doing this? (One optimisation is to have validate() return the index of the OP_ENDIF it finds, rather than a boolean; this would change runtime from quadratic-time to linear).
The best way of solving this is by using a Stack data structure. Every new opening instruction (e.g. OP_IF) is pushed into the stack. When you find a closing instruction (e.g. OP_ENDIF), you pop the top element of the stack and check if it is the corresponding opening instruction for that closing instruction. If so, then it's valid, and you proceed to the next step. In the end, if the stack is empty then the control flow you're checking is correct. Otherwise, it's not.
I am working with googlecode lanterna libraries. One of it's methods is "moveCursor(int x, int y)". I have a terminal field, and I want to move a character in it. But I'm having two problems:
The cursor does not go in the proper way it should. When I press Left Arrow after I have been pressing Right Arrow, it goes some steps down, than goes the right way. That happens for all arrows.
And the second question. Can anyone help me to move a character in the terminal field? Should I build any class or any method? Or I should modify this?
Thank you!
public void movePlayer()
{
int xLocation = s.getXLocation();
int yLocation = s.getYLocation();
while (true)
{
Key key = t.readInput();
if (key!=null)
{
if (key.getKind() == Key.Kind.ArrowLeft)
{
t.moveCursor(xLocation-1, yLocation);
xLocation--;
}
else if (key.getKind() == Key.Kind.ArrowRight)
{
t.moveCursor(xLocation+1, yLocation);
xLocation++;
}
else if (key.getKind() == Key.Kind.ArrowUp)
{
t.moveCursor(xLocation, yLocation+1);
yLocation--;
}
else if (key.getKind() == Key.Kind.ArrowDown)
{
t.moveCursor(xLocation, yLocation-1);
yLocation++;
}
}
}
}
If you do it like this the cursor moves properly and without any complications.
public static void movePlayer() {
int xLocation = s.getXLocation();
int yLocation = s.getYLocation();
while (true) {
Key key = t.readInput();
if (key != null) {
if (key.getKind() == Key.Kind.ArrowLeft) {
t.moveCursor(xLocation - 1, yLocation);
xLocation--;
} else if (key.getKind() == Key.Kind.ArrowRight) {
t.moveCursor(xLocation + 1, yLocation);
xLocation++;
} else if (key.getKind() == Key.Kind.ArrowUp) {
t.moveCursor(xLocation, yLocation - 1);
yLocation--;
} else if (key.getKind() == Key.Kind.ArrowDown) {
t.moveCursor(xLocation, yLocation + 1);
yLocation++;
}
}
}
}
I hope I could help you with your Problem.
To your second question I can't give an answer so far.
#Override
public boolean onTouchEvent(MotionEvent event)
{
synchronized (getHolder())
{
int aktion = event.getAction();
if (aktion == MotionEvent.ACTION_DOWN)
{
touched = true;
bar.shareTouch(event.getX(), event.getY(), touched);
}
else if (aktion == MotionEvent.ACTION_UP)
{
touched = false;
bar.shareTouch(event.getX(), event.getY(), touched);
}
if (aktion == MotionEvent.ACTION_POINTER_DOWN)
{
touched2 = true;
bar.shareTouch2(event.getX(), event.getY(), touched2);
}
else if (aktion == MotionEvent.ACTION_POINTER_UP)
{
touched2 = false;
bar.shareTouch2(event.getX(), event.getY(), touched2);
}
}
return true;
}
This is a Code to chech if first Finger is going onto the screen or leaving it. The same for another finger.
public void shareTouch2(float xTouch2, float yTouch2, boolean touched2)
{
if (xTouch2 <= gameViewWidth/2) {
if (touched2 == true) {
touchedLeft2 = true;
}
else if(touched2 == false) {
touchedLeft2 = false;
}
}
else if (xTouch2 > gameViewWidth/2) {
if (touched2 == true) {
touchedRight2 = true;
}
else if(touched2 == false) {
touchedRight2 = false;
}
}
}
public void shareTouch(float xTouch, float yTouch, boolean touched)
{
if (xTouch <= gameViewWidth/2) {
if (touched == true) {
touchedLeft = true;
}
else if(touched == false) {
touchedLeft = false;
}
}
else if (xTouch > gameViewWidth/2) {
if (touched == true) {
touchedRight = true;
}
else if(touched == false) {
touchedRight = false;
}
}
}
private void moveRight()
{
x += 3;
}
private void moveLeft()
{
x -= 3;
}
private void checkTouch() {
if ((touchedLeft == true && touchedRight2 == false) || (touchedLeft2 == true && touchedRight == false)) {
moveLeft();
}
else if ((touchedLeft == false && touchedRight2 == true) || (touchedLeft2 == false && touchedRight == true)) {
moveRight();
}
else if ((touchedLeft == true && touchedRight2 == true) || (touchedLeft2 == true && touchedRight == true)) {
}
}
The checkTouch() is called in the onDraw() Method. Now if I place a finger on the right side of the screen it moves right. Same for left. But if I touch left and the right without removing the left finger the Object still moves left although it should stop. Now when I leave the left finger it still moves left although it should move right.
I hope you understand my problem.
Hope you can help
You can't just assume the ACTION_POINTER_UP Event will only be sent for the same finger ACTION_POINTER_DOWN was sent.
Just as the ACTION_DOWN event is always fired for the first finger to touch down, the ACTION_UP event is only fired for the last finger to lift (i.e. when there are no more fingers on the screen). All others will get an ACTION_POINTER_UP event, even if it's the finger that started the gesture.
However, the Android documentation does specify
Each pointer has a unique id that is assigned when it first goes down [and] remains valid until the pointer eventually goes up.
So in theory, your first and second finger should still have the same ID, regardless whether the Event that reports them.
The solution is simple, then: Use getPointerCount() and getPointerID() to keep track of your fingers.
This may be easier if you refactor your code to account for more than two fingers by replacing the Booleans touchedLeft and touchedLeft2 with a single counter, e.g. fingersOnLeftSide - which has the neat side effect of only needing one shareTouch() method and otherwise reducing redundancy in your code.
EDIT:
Disclaimer: This is just off the top of my head, untested and written without knowledge of any of your code other than what you posted. Not necessarily the best way to solve your problem, but the shortest I could think of.
This is the Event handler:
public boolean onTouchEvent(MotionEvent event)
{
synchronized (getHolder())
{
int aktion = event.getAction();
if (aktion == MotionEvent.ACTION_DOWN || aktion == MotionEvent.ACTION_POINTER_DOWN
|| aktion == MotionEvent.ACTION_UP || aktion == MotionEvent.ACTION_POINTER_UP)
{
bar.clearTouches();
for (int i = 0; i < event.getPointerCount(); i++) {
bar.shareTouch(event.getX(i)); // we don't need the y coordinate anyway
}
}
}
return true;
}
The rewritten shareTouch() to go along with it, as well as clearTouches() I introduced to make this simpler:
private void shareTouch(float x)
{
if (x < gameViewWidth/2) {
fingersLeft++;
} else {
fingersRight++;
}
}
private void clearTouches()
{
fingersLeft = 0;
fingersRight = 0;
}
And finally, the new checkTouch():
public void checkTouch()
{
if (fingersLeft > fingersRight) {
moveLeft();
} else if (fingersRight > fingersLeft) {
moveRight();
}
}