I have 3 areas set up to act like buttons in my application, they work, but for some reason I have to click it multiple times before it does what it's supposed to do. Is this because it's checking if the user has click in that specific area?
(I'm using LWJGL/Slick2D)
public void update(GameContainer gc, StateBasedGame sbg, int delta)throws SlickException {
int xpos = Mouse.getX();
int ypos = Mouse.getY();
//Play Game Button
if((xpos > 276 && xpos < 556 ) && (ypos > 230 && ypos < 270)) {
if(Mouse.isButtonDown(0)) {
sbg.enterState(1);
click = new Sound("res/click.wav");
click.play();
TOW = new Music("res/TownOfWishes.ogg");
TOW.loop();
TOW.setVolume(0.1f);
}
}
//Exit Game Button
if((xpos > 276 && xpos < 556 ) && (ypos > 154 && ypos < 195)) {
if(Mouse.isButtonDown(0)) {
click = new Sound("res/click.wav");
click.play();
System.exit(0);
}
}
//Settings Game Button
if((xpos > 276 && xpos < 556 ) && (ypos > 80 && ypos < 121)) {
if(Mouse.isButtonDown(0)) {
click = new Sound("res/click.wav");
click.stop();
sbg.enterState(2);
}
}
}
Your code looks good but your problem could be your coordinate system(orthographic matrix setup) or your actual calculation itself. Try double checking your math.
Related
In the setup function i clear the EEPROM if a specific button is clicked.
in the loop function at the start i have this code:
if(millis() - last_sample >= 180){
sampler();
EEPROM.get(stateEEPROMAdress, stateCode);
stateCode = getState(stateCode);
EEPROM.put(stateEEPROMAdress, stateCode);
Serial.println(stateCode);
}
and a bunch of sampling code.
then at the end of the loop i have:
if(millis() - last_xbee >= 900){
EEPROM.get(packetEEPROMAdress,packetCount );
EEPROM.get(stateEEPROMAdress,stateCode);
if(!initializing || (stateCode!= 0 && stateCode != 1)){
telemetry[2] = packetCount++;}
telemetry[21] =stateCode;
EEPROM.put(packetEEPROMAdress, packetCount);
.... and printing codes...
I also at the start of the sketch i have defined :
const int packetEEPROMAdress = 0;
const int stateEEPROMAdress = packetEEPROMAdress + sizeof(int);
and this is the getState function. simple state determination from sensor values:
int getState(const int stateCode=0){
int outState;
//state 0
if(stateCode == 0 &&(fabs(verticalSpeed) < 2 || fabs(relativeAltitude) < 5)&&initializing){
outState = 0;
//true should change later to see is launch botton is on
} else
if(missionReady && !initializing && stateCode == 0){
outState = 1;
}else if(verticalSpeed > 3&&stateCode == 1){
outState = 2;
}
//else
//if(VerticalSpeed < 3 && stateCode == 2){
// stateCode = 2;
// //apogee but no code in CDR
//}
else if(verticalSpeed < 2 &&stateCode == 2){
outState = 3;
} else if((fabs(relativeAltitude - 450)< 10 || relativeAltitude<440 ) &&stateCode == 3){
outState = 4;
}else
//true should be replaced with seperation photocell is bright
if(true && stateCode == 4){
outState = 5;
}else if(relativeAltitude < 3 && fabs(verticalSpeed) < .7 && stateCode == 5 ){
outState == 6;
//activate Buzzer stop telemetry
}
return outState;
}
everything a good when state is 0 . when i send a command and states becomes 1. the after a few loops that 1 appears. the number in EEPROM becomes 8663 . is there a problem in addressing the EEPROM?
It was sth silly:)
Nothing related to EEPROM.
I didn't give a initial value to outState so large number stored in EEPROM,
Sorry if i got your time:)
var xpos = 0;
var ypos = 0;
xpos = obj_magnet.x;
ypos = obj_magnet.y;
if (xpos > 435 && xpos < 704 && ypos > 350 && ypos < 640)
{
with(obj_lamp)
{
instance_change(obj_lamp_light, true);
}
if obj_lamp_light.image_index == 5
{
obj_lamp_light.image_speed = 0;
}
with(obj_arrow)
{
instance_change(obj_arrow_move_one_direction, true);
}
if obj_arrow_move_one_direction.image_index == 4
{
obj_arrow_move_one_direction.image_speed = 0;
}
with(obj_arrow_move_opposite_direction)
{
instance_change(obj_arrow, true);
}
exit;
}
else
{
with(obj_lamp_light)
{
instance_change(obj_lamp, true);
}
with(obj_arrow_move_one_direction)
{
instance_change(obj_arrow_move_opposite_direction, true);
if obj_arrow_move_opposite_direction.image_index == 4
{
obj_arrow_move_opposite_direction.image_speed = 0;
}
}
exit;
}
This is a game which I am trying to create where the obj_arrow_move_opposite_direction and obj_arrow_move_one_direction contains 5 sub images and the obj_lamp_light contains 5 sub images.
You stated that each object contains 5 sub-images, correct? Looks like you're looking for a nonexistent sub-image (5) on line 7.
This appears to be a simple typo, but if not it's important to note that image_index starts at 0. So 5 images would be 0-4, rather than 1-5.
var xpos=0;
var ypos=0;
xpos=obj_magnet.x;
ypos=obj_magnet.y;
if(xpos>435&&xpos<704&&ypos>350&&ypos<640) { with(obj_lamp){
instance_change(obj_lamp_light,true);} if
obj_lamp_light.image_index==5{ obj_lamp_light.image_speed=0;} // should be object_lamp_light.image_index == 4
with(obj_arrow){
instance_change(obj_arrow_move_one_direction,true);}
if obj_arrow_move_one_direction.image_index==4{
obj_arrow_move_one_direction.image_speed=0;}
with(obj_arrow_move_opposite_direction){
instance_change(obj_arrow,true);}
exit;
}
else{
with(obj_lamp_light){
instance_change(obj_lamp,true);}
with(obj_arrow_move_one_direction){
instance_change(obj_arrow_move_opposite_direction,true);
if obj_arrow_move_opposite_direction.image_index==4{
obj_arrow_move_opposite_direction.image_speed=0;}}
exit;
}
Better yet, if you're checking to make sure that the object's image_indexes are equal to the last sub-image you could use image_number and subtract by one. This way if you ever add more sub-images you could ensure your code is still checking for the last frame.
I want to keep my QMainWindow always inside of the desktop, so I add the implementation for QMainWindow::moveEvent :
void MainWindow::moveEvent(QMoveEvent *ev)
{
if(ev->pos().x() < 0) setGeometry(0, ev->oldPos().y(), width(), height());
}
But when I move the window to out of desktop left bounding, the app is crashed.
What is wrong with this code? Why it is crashed? Is my solution correct?
//--Update:
I tried with this:
int newx = ev->pos().x(),
newy = ev->pos().y();
if(ev->pos().x() < 0) newx = 0;
if(ev->pos().y() < 0) newy = 0;
move(newx, newy);
It worked without crash but I'm not satisfied because of the moving is not smooth.
This should smoothly help with the upper left corner .. but you'll need to add some more conditions to get it working for all four sides.
posX and posY are member variables.
void MainWindow::moveStep() { // [SLOT]
int movX = 0, movY = 0;
if(posX < 0) movX = 1;
if(posY < 0) movY = 1;
move(posX + movX, posY + movY);
}
void MainWindow::moveEvent(QMoveEvent *ev) {
if(ev->pos().x() < 0 || ev->pos().y() < 0) {
posX = ev->pos().x();
posY = ev->pos().y();
QTimer::singleShot(10, this, SLOT(moveStep()));
}
}
To have it even more elegantly consider using QVariantAnimation with a QRect and setGeometry().
I am writing the recursive method for a minesweeper game and I am encountering a stackOverflow error in the recursive method that clears out empty spaces, The error does not occur when checking for 3 of the surrounding spaces but only when checking all eight. Can you please help identify the issue?
The stack trace is :
Exception in thread "AWT-EventQueue-0" java.lang.StackOverflowError
at java.awt.Component.firePropertyChange(Component.java:8419)
at javax.swing.AbstractButton.setText(AbstractButton.java:306)
at Minesweeper.Minesweeper.showTile(Minesweeper.java:105)
at Minesweeper.Minesweeper.clearEmpty(Minesweeper.java:137)
at Minesweeper.Minesweeper.clearEmpty(Minesweeper.java:177)
The class:
public class Minesweeper implements ActionListener {
JFrame frame = new JFrame("Minesweeper");
JButton reset = new JButton("Reset");
JButton solve = new JButton("Solve");
JToggleButton[][] buttons = new JToggleButton[20][20];
int[][] counts = new int [20][20];
Container grid = new Container();
final int MINE = 10;
public static void main(String[] args)
{
new Minesweeper();
}
public Minesweeper()
{
frame.setSize(600, 600);
frame.setLayout(new BorderLayout());
frame.add(reset, BorderLayout.NORTH);
frame.add(solve, BorderLayout.SOUTH);
reset.addActionListener(this);
solve.addActionListener(this);
grid.setLayout(new GridLayout(20, 20));
for (int r = 0; r < buttons.length; r++) {
for (int c = 0; c < buttons[0].length; c++) {
buttons[r][c] = new JToggleButton();
buttons[r][c].addActionListener(this);
grid.add(buttons[r][c]);
buttons[r][c].setSize(frame.getWidth() / 20, frame.getHeight() / 22);
}
}
frame.add(grid,BorderLayout.CENTER);
addRandomMines();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public void addRandomMines()
{
ArrayList<Integer> mineList = new ArrayList<Integer>();
for (int x = 0; x < counts.length; x++) {
for (int y = 0; y < counts[0].length; y++){
mineList.add((x*100)+y);
}
}
counts = new int[20][20];
for (int i = 0; i < 30; i++) {
int choice = (int)(Math.random()*mineList.size());
counts[mineList.get(choice)/100][mineList.get(choice)%100] = MINE;
mineList.remove(choice);
}
for (int x = 0; x < counts.length; x++) {
for (int y = 0; y < counts[0].length; y++){
if (counts[x][y]!=MINE) {
int mineCount = 0;
if (x > 0 && y > 0 && counts[x - 1][y - 1] == MINE)
mineCount++;
if (y > 0 && counts[x][y - 1] == MINE)
mineCount++;
if (x > 0 && counts[x - 1][y] == MINE)
mineCount++;
if (x < counts.length - 1 && counts[x + 1][y] == MINE)
mineCount++;
if (y < counts.length - 1 && counts[x][y + 1] == MINE)
mineCount++;
if (x < counts.length - 1 && y < counts.length - 1 && counts[x + 1][y + 1] == MINE)
mineCount++;
if (x > 0 && y < counts.length - 1 && counts[x - 1][y + 1] == MINE)
mineCount++;
if (x < counts.length - 1 && y > 0 && counts[x + 1][y - 1] == MINE)
mineCount++;
counts[x][y] = mineCount;
}
}
}
}
public void showTile(int r, int c)
{
if (counts[r][c] == 0) {
buttons[r][c].setText("");
buttons[r][c].setSelected(true);
}
else if (counts[r][c]==MINE) {
buttons[r][c].setForeground(Color.red);
buttons[r][c].setText("X");
buttons[r][c].setSelected(true);
}
else {
buttons[r][c].setText(counts[r][c] + "");
if (counts[r][c]==1)
buttons[r][c].setForeground(Color.blue);
else if (counts[r][c]==2)
buttons[r][c].setForeground(Color.magenta);
else if (counts[r][c]==3)
buttons[r][c].setForeground(Color.green);
buttons[r][c].setSelected(true);
}
}
public void lostGame() {
for (int x = 0; x < buttons.length; x++) {
for (int y = 0; y < buttons[0].length; y++) {
if (counts[x][y]==MINE) {
showTile(x, y);
}
}
}
}
public void clearEmpty(ArrayList<Integer> toClear)
{
if (toClear.size()==0){
return;
}
else {
int x = toClear.get(0)/100;
int y = toClear.get(0)%100;
toClear.remove(0);
if (counts[x][y]==0) {
if (x > 0 && y > 0) {
showTile(x-1,y-1);
if (counts[x-1][y-1]==0)
toClear.add((x-1)*100 + (y-1));
}
if (y > 0) {
showTile(x,y-1);
if (counts[x][y-1]==0)
toClear.add(x*100 + (y-1));
}
if (x <counts.length-1 && y > 0) {
showTile(x+1,y-1);
if (counts[x+1][y-1]==0)
toClear.add((x+1)*100 + (y-1));
}
if (x > 0) {
showTile(x-1,y);
if (counts[x-1][y]==0)
toClear.add((x-1)*100 + y);
}
if (x <counts.length-1 && y > 0) {
showTile(x+1,y);
if (counts[x+1][y]==0)
toClear.add((x+1)*100 + y);
}
if (x > 0 && y < counts[0].length-1) {
showTile(x-1,y+1);
if (counts[x-1][y+1]==0)
toClear.add((x-1)*100 + (y+1));
}
if (y < counts[0].length-1) {
showTile(x,y+1);
if (counts[x][y+1]==0)
toClear.add(x*100 + (y+1));
}
if (x <counts.length-1 && y < counts[0].length-1) {
showTile(x+1,y+1);
if (counts[x+1][y+1]==0)
toClear.add((x+1)*100 + (y+1));
}
}
clearEmpty(toClear);
}
}
#Override
public void actionPerformed(ActionEvent event) {
if (event.getSource().equals(reset)) {
for (int r = 0; r < buttons.length; r++) {
for (int c = 0; c < buttons[0].length; c++) {
buttons[r][c].setSelected(false);
buttons[r][c].setText("");
}
}
addRandomMines();
} else if (event.getSource().equals(solve)) {
} else {
for (int r = 0; r < buttons.length; r++) {
for (int c = 0; c < buttons[0].length; c++) {
if (event.getSource().equals(buttons[r][c])) {
if (counts[r][c] == MINE) {
showTile(r, c);
lostGame();
}
else if (counts[r][c] == 0) {
ArrayList<Integer> toClear = new ArrayList<Integer>();
toClear.add(r*100+c);
clearEmpty(toClear);
}
else {
showTile(r, c);
}
}
}
}
}
}
}
I think that you're using the wrong algorithm...
Try to use an iterative instead of an recursive approach.
As User404 already mentioned your current algorithm keeps the list growing...
For your implementation: you have 400 tiles. Assuming (worst case) all tiles are empty you call your method clearEmpty() once. You will find out that all 8 neighbors are empty so you add this 8 neighbors to the list while only removing the first one. Now you pass the array to the method again (2nd call) and will find 8 neighbors for the first entry again. So your 3rd call will have a list with 15 tiles.
Real problem
This way you will never come to an end as you never check if the current checked tile is already cleared but you only add to the list more than you will ever remove.
Solution
At least you should check if the tile you want to add to the list is already cleared or is already in the list.
You example is a clear example why recursive algorithms should be used with care as the termination is difficult sometimes and also you have to take care that no work is done multiple times.
I know the dotnetkicks.com system is open source so I can view the code myself but I can't make sense of how they did their paging. It's hard to explain but if you goto dotnetkicks.com you can play with the paging on their front page.
What I am specifically interested in is how they show the first few pages, then "..." and then the last few pages.
It starts off like this
Prev 1 2 3 4 5 6 ... 355 356 Next
Then if you hit page 10 it changes to this
Prev 1 2 ... 6 7 8 9 10 11 12 13 14 ... 355 356 Next
It's by far my favorite paging system so I'd like to do the same thing on my websites
The Pagination control in the project is fairly straight forward, if you've ever written a paging control. I think what may be confusing you is the use of urlrewriting.net for the /page/n url format.
I've written such a control and it took some code... there are plenty decisions to take.
public class SimplePagerLinkGenerator : IPagerLinkGenerator
{
private PagingDisplaySettings _displaySettings;
public SimplePagerLinkGenerator(PagingDisplaySettings displaySettings)
{
this._displaySettings = displaySettings;
}
public PageLinkData[] GetPagesLinkData(uint crtPageIndex, uint pageCount, ushort pageSize,
string urlLinkTemplate)
{
int i, crtPage = (int)crtPageIndex, pageCnt = (int)pageCount,
pgInnerCnt = (int)this._displaySettings.PagesBeforeOrAfterCurrent,
pgEndCnt = (int)this._displaySettings.PagesShownAtEndingsCount;
int innerBlockStart = crtPage - pgInnerCnt;
int innerBlockEnd = crtPage + pgInnerCnt;
int innerBlockStartNormalized = innerBlockStart < 1 ? 1 : innerBlockStart;
int innerBlockEndNormalized = innerBlockEnd > pageCount ? pageCnt : innerBlockEnd;
List<PageLinkData> result = new List<PageLinkData>(2 * pgEndCnt + 3 + 2 * pgInnerCnt);
for (i = 1; i <= pgEndCnt && i <= pageCount; i++)
result.Add(new PageLinkData(i, i == crtPage, urlLinkTemplate, pageSize));
if (i > pageCount)
return result.ToArray();
if (innerBlockStart > pgEndCnt + 1)
{
result.Add(PageLinkData.Ellipsis);
for (i = innerBlockStart; i <= innerBlockEndNormalized; i++)
result.Add(new PageLinkData(i, i == crtPage, urlLinkTemplate, pageSize));
}
else
for (i = pgEndCnt + 1; i <= innerBlockEndNormalized; i++)
result.Add(new PageLinkData(i, i == crtPage, urlLinkTemplate, pageSize));
if (innerBlockEnd < pageCount - pgInnerCnt)
{
result.Add(PageLinkData.Ellipsis);
for (i = pageCnt - pgInnerCnt + 1; i <= pageCount; i++)
result.Add(new PageLinkData(i, i == crtPage, urlLinkTemplate, pageSize));
}
else
for (; i <= pageCount; i++)
result.Add(new PageLinkData(i, i == crtPage, urlLinkTemplate, pageSize));
return result.ToArray();
}
public PagingDisplaySettings DisplaySettings { get { return this._displaySettings; } }
}