I have a group of objects within a game that is a sensor(let's call them collectively object1). When it collides with my main object (object2), the score increments by 10. However, after each subsequent restart of the scene(not the whole game), each collision between object1 and object2 duplicates itself, then triplicates and so forth.
So for the first running of the scene, object1 collides with object2 once(I know this because I have a print statement every time the 2 objects collide). The second time it collides twice, the third time three times and so forth. I presume I am not removing a certain feature of the sensor but I cannot figure out what it is. How do I correctly remove the objects if this is the problem?
My code for the removal of object1 on collision:
local function onCollision( self,event )
if(event.object2.name == "bonus")then--if we hit a bonus ball
event.object2:removeSelf()--removes the bonus ball object from the scene
print("bonus collided")
display.remove(event.object2)
game.addToScore(10)--adds a value of 10 to the score
scoreText.text = game.returnScore()
Runtime:removeEventListener("enterFrame", event.object2)
else
composer.gotoScene("restart")
Runtime:removeEventListener("touch", onObjectTouch)
end
end
I studied your code and in short this is the problem
ball.collision = onCollision
It's located under scene:show and therefore a new eventListener will be created each time that you to the scene. And it's not being removed under scene:hide.
Basically half of your code doesn't really do anything. For exampel you remove the same item twice, add Runtime listeners to objects (not functions) and you're trying to remove thise Runtime listeners. For example this tries to remove a Runtime event listener on a display object that doesn't even exist:
Runtime:removeEventListener( "collision", circle )
What you need to do is:
Create all objects and listeners under scene:create
Use local collision handling (i.e. not Runtime listeners): https://docs.coronalabs.com/daily/guide/physics/collisionDetection/index.html#local-collision-handling
Rewrite your code so that you have functions and listeners outside of the scene:create
Related
Hi I'm implementing click listeners in the following way but after some time the methods and variables inside the listener's closure get the wrong values or something. Let me explain the implementation of the listener a little better a for loop creates the listener for a set of image views then later in the program the for loop is called a second time and it resets the listener methods and variables to different values. Everything works great for about 30 minutes but then for some reason, the listener's methods and variables start having the wrong values. Has anybody ever heard of this behavior or can tell me where I've gone wrong with the code? Keep in mind that the listener I'm about to paste here is just a small piece of a 1014 line class. I'm hoping somebody can spot How I'm implementing the listener wrongly and can give me some advice on how to "reset" the listener so that it's variables and values stay over time. Hopefully you can read the code without putting it in an editor but feel free to copy it for readability's sake Here is the code for the image view listener with comments.
//image views are held in an array
//set an image view in its imageview container
imgArr0[slotId1].invalidate()
imgArr0[slotId1].setImageDrawable(null)
//drw is not defined in this example
imgArr0[slotId1].setImageDrawable(drw)
/*if video or image id is set to image then set a listener for the image
*/
/*slotId1 is not defined in this example but it is simply a counter to iterate over the ImageView array
*/
if (videoOrImageId0[slotId1] == "image") {
//null any listeners that might be attached to the image view
imgArr0[slotId1].setOnClickListener(null)
//set or reset the listener
imgArr0[slotId1].setOnClickListener() {
`enter code here`//if the current config is portrait then set a new image image
if (currentConfig0 == "portrait0") {
act0.lrgImage0.invalidate()
act0.lrgImage0.setImageDrawable(null)
/*drw is not defined in this example but works fine in the production script
*/
act0.lrgImage0.setImageDrawable(drw)
}
--calmchess
ccc tv application with problem.
(https://i.stack.imgur.com/PjdbN.jpg)![enter image description here](https://i.stack.imgur.com/FaMnc.
I was able to partially solve this question by destroying all the image views and their associated click listeners then rebuilding those... However I don't consider this issue completely solved so if anybody can provide a better solution I'd love to hear it because rebuilding the images every few minutes has to be using a lot of unnecessary hardware resources.
--calmchess
I'm using the MPAndroidChart library in my app to render a line chart, and am facing an issue while adding more data dynamically to the chart. I tried going through the existing StackOverflow questions and also the GitHub issues for this library, but couldn't find a fix for my issue.
I'm using the LineChart API. In my use case i need to first show 15 data points on the chart, and once the user scrolls to the boundary, I'm fetching 15 more data points from the backend and resetting the data object with the set of 30 data points.
My logic for checking if the user reached the boundary is:
#Override
onChartTranslate {
.
.
if (!isLoading) {
if (lineChart.getHighestVisibleX() == lineChart.getXChartMax()) {
isLoading = true;
fetchMoreData();
}
}
.
.
}
Below method fetches data from the backend, and then updates the chart
fetchMoreData {
dataObservable.subscribe(newData -> updateUI(newData))
}
the update chart method with additional data
updateUI(newData) {
//from the data received, create new dataset,
//create a new lineData Object, and add this dataSet
//set the lineData object on the chart using
lineChart.setData(newLineDataSet)
//view port updates which consist of below
lineChart.setVisibleXRangeMinimum(4);
lineChart.setVisibleXRangeMaximum(4);
lineChart.setAutoScaleMinMaxEnabled(true);
lineChart.moveViewToX(previousBoundary)
lineChart.highlightValue(previouslyHighlightedValue)
isLoading = false
}
Things work fine for me, when i scroll slowly beyond the boundary, i.e., backend call to fetch additional data is fired and I get the new 15 data points, and I replace the existing lineData object with the new lineData object which has (old + new) data points.
I'm facing an issue if I scroll too quick, that the fetchMoreData is getting called multiple times (2/3 times), and the chart draws more data.
On debugging this I noticed that the lineChart.getHighestVisibleX() method is returning an incorrect value sometimes causing this to happen.
For e.g., the first call is triggered when the highestVisibleX equals the maxX value of 14. This updates the chart with new data points (now 30), and during redrawing of the chart, the onTranslate method gets called and the highestVisibleX somehow returns 29 (same value as maxX for the new data) even though the highest visible x-value is 14.
Could someone please help me with this issue?
On developing a painting canvas application in android, i need to track all the points and have to redraw it in another canvas. Now i am able to track all the points, but don't know how to synchronize the point drawing in case of draw and redraw ie the user should redraw the points at the same time gap as in the draw. How can i achieve this?
Not sure if this is the sort of answer you are looking for but I would record the events with a sort of timestamp, really a time difference to the next point. Something like:
class Point {
int x;
int y;
long deltaTime;
}
Its up to you how precise you want to be with the timing. Second to millisecond precision should be good enough. You could interpret deltaTime as either the time until this point should be drawn or the time until the next point should be drawn (I'm going to use the latter in my example).
A few reasons to use a deltaTime instead of a direct timestamp is that it lets you check for really long pauses and you are going to have to compute the delta time anyways in playback. Also using it as a long should give you enough room for really lengthy pauses and lets you use the Handler class which accepts a long integer for the number of milliseconds to wait before executing.
public class Redrawer implements Handler.callback {
LinkedList<Point> points; //List of point objects describing your drawing
Handler handler = new Handler(this); //Probably should place this in class initialization code
static final int MSG_DRAW_NEXT = 0;
public void begin(){
//Do any prep work here and then we can cheat and mimic a message call
//Without a delay specified it will be called ASAP but on another
//thread
handler.sendEmptyMessage(MSG_DRAW_NEXT);
}
public boolean handleMessage(Message msg){
//If you use the handler for other things you will want to
//branch off depending on msg.what
Point p = points.remove(); //returns the first element, and removes it from the list
drawPoint(p);
if (!points.isEmpty())
handler.sendEmptyMessageDelayed(MSG_DRAW_NEXT, p.deltaTime);
public void drawPoint(Point p){
//Canvas drawing code here
//something like canvas.drawPixel(p.x, p.y, SOMECOLOR);
//too lazy to look up the details right now
//also since this is called on another thread you might want to use
//view.postInvalidate
}
This code is far from complete or bullet-proof. Namely you will need to possibly pause or restart the redrawing at a later time because the user switched activities or got a phone call, etc. I also didn't implement the details of where or how you get the canvas object (I figure you have that part down by now). Also you probably want to keep track of the previous point so you can make a rectangle to send to View.postInvalidate as redrawing a small portion of the screen is much faster than redrawing it all. Lastly I didn't implement any clean-up, the handler and points list will need to be destroyed as needed.
There are probably several different approaches to this, some probably better than this. If you're worried about long pauses between touch events simply add a check for the deltaTime if its greater than say 10 seconds, then just override it to 10 seconds. Ex. handler.sendEmptyMessage(MSG_DRAW_NEXT, Math.min(p.deltaTime, 100000)); I'd suggest using a constant instead of a hard coded number however.
Hope this helps
I have a game which displays an array of colored blocks. The user can move these blocks around the screen. When a touch event occurs, I take note of the cell that has been touched (cell[i][j].isMoving = true). If the user moves the block around I draw the rectangle relative to an offset value. When a touch up event is detected, I check whether or not the user has dragged the block far enough to signify a moving of a block.
My basic draw loop is as follows:
for(int i = 0; i < xCells, i++){
for(int j = 0; j < yCells; j++){
if(cell[i][j].isMoving)
canvas.drawRect(...) // draw with offsets
else
canvas.drawRect(..)
}
}
The problem I am having is when a user releases the block it occasionally flickers briefly.
When a touch up event occurs, the offset must be set to 0, the coordinates of the block changed (if requirements are met) and isMoving has to be set to false.
As I have a thread constantly running that calls the draw code above, it appears that the UI thread is altering the array of blocks, meaning it is in an inconsistent state when the draw method occurs.
Does anyone have suggestions on how to fix this? Could I use a handler? I've tried synchronizing the onTouchEvent method and the onDraw method, but this seems to occasionally block user input
thanks
The safe solution is to only allow one thread to create objects, add and remove them from a List or array after the game has started.
I had problems with random AIOOBEs (Array Index Out Of Bounds Exception) errors and no synchornize could solve it properly plus it was slowing down the response of the user.
My solution, which is now stable and fast (never had an AIOOBEs since) is to make UI thread inform the game thread to create or manipulate an object by setting a boolean flag and coordinates of the touch into simple variables.
Since the game thread loops about 60 times per second this proved to be sufficent to pick up the message from the UI thread and do something about it.
In your case onTouch event should never alter cell[i][j] directly but only set some integer to a particluar value. Then your thread would at some point evaluate this variables and set cell[i][j] and then draw, so onTouch can never unpredictably interfear with your thread.
This is a very simple solution and it works great...
Just want to start out by saying this seems like a great site, hope you guys can help!
I'm trying to use the structure laid out in LunarLander to create a simple game in which the user can drag some bitmaps around on the screen (the actual game is more complex, but that's not important). I ripped out the irrelevant parts of LanderLander, and set up my own bitmap drawing, something like
BoardThread (an inner class of BoardView):
run()
{
while(mRun)
{
canvas = lockSurfaceHolder...
syncronized(mSurfaceHolder)
{
/* drawStuff using member position fields
in BoardView */
}
unlockSurfaceHolder
}
}
My drawStuff simply walks through some arrays and throws bitmaps onto the canvas. All that works fine. Then I wanted to start handling touch events so that when the user presses a bitmap, it is selected, when the user unpresses a bitmap, it is deselected, and if a bitmap is selected during a touch move event, the bitmap is dragged. I did this stuff by listening for touch events in the BoardView's parent, BoardActivity, and passing them down into the BoardView. Something like
In BoardView
handleTouchEvent(MotionEvent e)
{
synchronized(mSurfaceHolder)
{
/* Modify shared member fields in BoardView
so BoardThread can render the bitmaps */
}
}
This ALSO works fine. I can drag my tiles around the screen no problem.
However, every once in a while, when the app first starts up and I trigger my first touch event, the handleTouchEvent stops executing at the synchronized line (as viewed in DDMS). The drawing loop is active during this time (I can tell because a timer changes onscreen), and it usually takes several seconds or more before a bunch of touch events come through the pipeline and everything is fine again.
This doesn't seem like deadlock to me, since the draw loop is constantly going in and out of its syncronized block. Shouldn't this allow the event handling thread to grab a lock on mSurfaceHolder? What's going on here? Anyone have suggestions for improving how I've structured this?
Some other info. This "hang" only ever occurs on first touch event after activity start. This includes on orientation change after restoreState has been called. Also, I can remove EVERYTHING within the syncronized block in the event handler, and it will still get hung up at the syncronized call.
Thanks!
So Rob Green from rbgrn helped me get a little more info on this. I ended up using a concurrent queue to deliver touch events to my game thread, but I still had hanging issues when saveInstanceState got called, so I'm now calling Thread.sleep(16) at the bottom of every iteration of my game thread's while loop. Full discussion here.