I'm creating a program that is going to play a video game. When it reads that their is an enemy in RAM value 0x0016 it needs to press B. I think maybe because of my while loop B is getting spammed way too much? I'm not sure. At the moment, on FCEUX it says the B button is getting pressed, but it stays orange. I need the B button to only be pressed once.
Here's my code:
JoypadB = {B=true}
JoypadRight = {right=true}
while (true) do
c = memory.readbyte(0x0016);
if (c == 6 ) then
joypad.set(1,JoypadB)
else
joypad.set(1,JoypadRight)
end;
gui.text(100,100,c);
emu.print(c);
emu.frameadvance();
end;
This question isn't really about FCEUX, and it isn't really about lua. It's 95% just about programming but a bit of videogaming commonsense will help. The button gets pressed repeatedly because 0x0016 contains 6 repeatedly. Add a toggle to effect repeated shots as long as there's an enemy. You may need to pick a different turbo interval than every-other, which is what's done in this example:
JoypadB = {B=true}
JoypadRight = {right=true}
toggle = 0
while (true) do
c = memory.readbyte(0x0016);
if (c == 6) then
if(toggle==0) then
joypad.set(1,JoypadB)
toggle = 1;
else
joypad.set(1,JoypadRight)
toggle = 0;
end
else
joypad.set(1,JoypadRight)
end;
emu.frameadvance();
end;
Or, to do what you literally asked for, assuming the enemy only takes one shot to kill, then just press the button once and wait until the next time the enemy disappears and then reappears:
c = memory.readbyte(0x0016);
joypad.set(1,JoypadRight)
if (c == 6) then
if(toggle==0) then
joypad.set(1,JoypadB)
toggle = 1;
end
else
toggle = 0;
end;
Related
I'm super frustrated with this.
first for you to understand my code - My goal here is for the user to get randomly selected word appear to them in a way that every letter sits inside of a box.
Then if the user clicks on a button called "Pick a word", another word will be selected and the correct number of boxes will appear.
I have an array of words like this:
var word_group_1 = ["abolsh", "absorbent", "betrayal", "frutish", "commensurate", "eonfident", "zite"]
I'm using this function to select a random word from that array then splice it.. works perfectly:
function random_word_genereator() {
random = randomNumber(0, word_group_1.length);
//putting the chosen word from array in the chosen word variable
chosen_word = word_group_1[random]
//after we used the chosen word were removing it from the away
word_group_1.splice(random, 1)
//splitting the chosen word into an array
chosen_word_letters_arry = chosen_word.split("")
}
in a button click of "pick a word"- I'm creating 5 instances of a Movieclip I have in my library (just a blue box to put text in it) with text in at like this:
function create_boxes(e)
{
//to know which word has been displayed to the user//
old_word=chosen_word
random_word_genereator()
for (i=0;i<chosen_word.length;i++){
cell_boxes = new lib.cell_box();
stage.addChild(cell_boxes)
cell_boxes.name="cell_box"+i;
cell_boxes.x=(xlocation * i) + 50
cell_boxes.y = 80;
output = new createjs.Text();
cell_boxes.addChild(output)
output.text=chosen_word_letters_arry[i]
}
everything works fine on the first click As You Can View Here.
The word being selected and displayed on the stage
my problem is when I'm clicking Again on the button "pick a word"
its not deleting the correct number of boxes.
I'm putting visible false to the boxes which holds the "Old word" (the one I need to delete)
but As you can se here After I click again its getting messed up.
sometimes its's working, switches from 12 letter word, to a 4 one.
but it should be luck. I'm dying to get this to WORK! its for my school project.
Please help me!
Easy answer that will plug and play into your code:
js
...
//to know wichh word has been displayed to the user//
old_word=chosen_word
random_word_genereator()
for (i = 0; i < stage.numChildren; i++) // Loop through all children of the stage
if (stage.getChildAt(i) is lib.cell_box) // Checks if the child is a lib.cell_box
stage.removeChildAt(i--); // Removes child from stage and decrements i
for (i=0;i<chosen_word.length;i++){
...
Original answer (cleaner code, some restructuring):
It's best to break this kind of logic down into steps.
var boxes:MovieClip = new MovieClip();
boxes.y = 80;
addChild(boxes);
...
function createBoxes(word:String):void {
// Remove boxes first
while (boxes.numChildren > 0)
boxes.removeChildAt(0);
// Add boxes
for each(var c:String in word.split("")) {
var box:Box = new Box(c);
box.x = boxes.width + 50;
boxes.addChild(box);
}
}
Then set the text inside a Box class.
I have a UIimage which I want to move according to X and Y given by certain equations ( physics projectile time equations) and I want it to move every 1 second so that it would appear to the user as if it's actually moving not just disappearing and reappearing at the last position, plus the positions given off are wrong I think. I would appreciate any help for either or both problems.
So far I tried this:
The movement function:
func moveCannonBall(toX:Int , toY:Int ){
var frm: CGRect = ballimageview.frame
frm.origin.x = frm.origin.x + CGFloat(toX)
frm.origin.y = frm.origin.y - CGFloat(toY)
ballimageview.frame = frm
}
On button click it's supposed to take the user's inputs (gravity, angle, and the initial speed)
#IBAction func getAlpha( sender:AnyObject){
gravity = Float(g[pickerView.selectedRow(inComponent: 0)])
xMax = ((V0*V0)*sin(2.0*angle))/gravity
It's supposed to stop every 1 second but only the calculations pause every 1 second and the UIimage just disappears and reappears just
while Int(toX) < Int(xMax) {
sleep(1)
t = t + 1
toX = V0*cos(angle)*t
toY = -0.5*gravity*t*t + V0*sin(angle)*t
moveCannonBall(toX: Int(toX), toY: Int(toY))
}
}
Any help is appreciated.
As Losiowaty said UIView.animationWithDuration is the way to go. Check out this answer to see how the syntax is: https://stackoverflow.com/a/30992214/5257729
I'm trying to have a different amount of force applied to an object when the screen is tapped a different amount of times ( only once and twice ).
I'm not sure what I'm doing wrong. Here is the code:
local function moveUp(event)
if event.numTaps > 1 then
jumper:applyForce( 0, 250, jumper.x, jumper.y )
elseif event.numTaps < 1 then
jumper:applyForce( 0, 0, jumper.x, jumper.y )
else
jumper:applyForce( 0, 200, jumper.x, jumper.y )
end
end
-- start game
createPlayScreen( )
system.setTapDelay( 2 )
Runtime:addEventListener("tap", moveUp)
I've tried moving the Runtime:addEventListener into the function. I've also tried have the event.numTaps == 2 and event.numTaps == 1, but to no avail.
The issue is that the TapDelay refuses to wait for the second tap.
Any and all help is greatly appreciated
P.S. I have the seconds set to two for testing purposes, but once I find that this works, I will be lowering the time to like 0.3 or something
There are several issues with the strategy you are using. For one, it is not scalable (to more than two taps). But ok, maybe you are 100% sure you will never ever need more than 2 taps. The next problem is that event.numTaps can only be 1 or 2, yet your listener tests for < 1! This can never happen. The next problem is that when you tap twice, at least in the simulator (did not test on device) you get two events: one for the first tap with numTaps = 1, and another for 2nd tap with numTaps = 2. In other words, the Corona engine does not wait before emitting a one-tap event to know if a second tap event occurs within some time range. So you get two tap events for a two-tap event, there is no way of knowing in the handler whether you should "wait" to see if another tap might occur within an allowable delay to constitute a "two-tap" event instead.
What you will have to do is create your own N-tap event generator. Whenever a tap occurs, check if your timer has been started. If so, increase the tap count and reset the timer. If not, start the timer that expires some short delay later. If no other tap occurs in that delay, the count you have saved is your tap number. Reset the counter if your timer expires. I have created some functions that do this and I have put them all in a table "object":
local tapEvents = {
measureInterTapTime = false, -- set to true to measure how fast you can tap!
onTapHandler = nil, -- set this to your handler
-- implementation details
tapTimer = nil,
tapCounter = 0,
tapEventTime = 0,
doneTap = function(self, event)
self.tapTimer = nil
if self.onTapHandler then
self.onTapHandler(self.tapCounter)
end
self.tapCounter = 0
self.tapEventTime = 0
end,
-- end implementation details
tap = function(self, event)
self.tapCounter = self.tapCounter + 1
if self.tapTimer ~= nil then
timer.cancel(self.tapTimer)
self.tapTimer = nil
end
local delayMS = 250
self.tapTimer = timer.performWithDelay(delayMS, function(e) self:doneTap(e) end, 1)
-- check how much time between taps, for interest:
if self.measureInterTapTime then
if self.tapEventTime ~= 0 then
local interTapTime = system.getTimer() - self.tapEventTime
print("Time (ms) between taps:", interTapTime)
end
self.tapEventTime = system.getTimer()
end
end,
}
tapEvents.onTapHandler = function(tapCounter)
print(tapCounter .. "-tap event")
end
-- because tapEvents contains a 'tap' function, will get called automatically with self:
Runtime:addEventListener('tap', tapEvents)
This captures N-tap events without limit!! I have included a flag you can set to true if you want to print out the ms delay between single taps so you can determine what the optimum delay should be (you don't want delay to be too short or you might inadvertently break an N tap into two smaller events; you don't want it to be too long either, or user will have to noticeably wait to indicate "end of my multitap").
Tap events must be added to a display object, not to the Runtime.
If you have a display object jumper for example, use:
jumper:addEventListener("tap", moveUp)
More documentation here: http://docs.coronalabs.com/api/event/tap/index.html
I have an image that the user can drag to the right and it will spring back when the user releases it. I want to execute some code when a user drags it quickly and releases it. Now I have a very awkward requirement that the user can drag the image, then keep it still for any length of time (for example 5 seconds), then drag it quickly and release it. As long as the image is moving above a certain speed when it is released, it will execute the code. If it falls below the minimum speed, it executes some different code. So that means I can't calculate the length of time between the beginning of the gesture and the end and execute the code depending on the length of time. What can I do? I guess I somehow need to know the speed at which the image is moving in it's last 500 milliseconds before the gesture ends. However I've hit a brick wall figuring out how to do that. Any help would be greatly appreciated.
Can you please include an explanation and possible example code with your answer as that would be a great help.
If you get the start X,Y coordinates of when the image is dragged, and the X,Y coordinates for when the mouse is released, you can use pythagoras' theorm to calculate the distance between the two points: http://en.wikipedia.org/wiki/Pythagorean_theorem
Also, if you start a timer when the mouse is moved (and mouse button is down), and stop it in the mouseup event, you can calculate the speed using the time and distance (speed = distance / time)
edit following comments:
point delayedMousePos;
point previousMousePos;
bool secondDrag = false;
bool isStopped = false;
var timeFirstStopped;
var positionCount = 0;
array previousMousePositions[3];
// timer which monitors mouse position (set to an interval of say, 10ms)
function timerMonitorMousePos_Elapsed() {
point currentMousePos = getMousePos();
if (isStopped == false) {
if (positionCount >= 2) {
array_shift(previousMousePositions); // remove the first element of the array and move everything down to reindex numerical array to start counting from zero
positionCount = 2; // keep positionCount within array bounds
}
previousMousePositions[positionCount] = currentMousePos; // add the new position to the end of the 'stack'
positionCount++;
}
if (currentMousePos == previousMousePos) { // start check for stationary
isStopped = true;
if (timeFirstStopped == null) {
timeFirstStopped = NOW();
} else {
if (NOW() - timeFirstStopped >= 500) { // we have been stopped for at least 500ms (assumes time is counted in milliseconds)
secondDrag = true;
// previousMousePositions[0] = the mouse position 30ms before the mouse stopped
}
}
} else {
isStopped = false;
timeFirstStopped = null;
}
previousMousePos = currentMousePos;
}
I wouldn't use a timer. I would just save the starting date/time along with x,y position when the dragging starts.
When the dragging has ended, save the ending date/time and position. From those information, I can calculate the distance in pixel and duration in milliseconds.
After searching some more on the internet, I finally answered my own question.
I worked out what I needed to do:
My UIPanGestureRecognizer:
- (IBAction)handlePan3:(UIPanGestureRecognizer *)recognizer3
Get the velocity of the users finger moving across the screen:
CGPoint vel = [recognizer velocityInView:self.myView];
Then:
if (vel.x > /*value*/) {
// Your code
}
I was about to give up, but no! I got there in the end. Thanks for everyones help. I've upvoted one or two answers because they were helpful. bobnoble actually gave the suggestion to use velocityInView and I found this other stack overflow question which gave me the info I needed: iOS - Making sense of velocityInView on UIPanGesture
I have a manometer, this needs to spin from a minimum value to a maximum. right now I have the manometer as a picture and the arrow as a movieclip. I've got it spinning at the right speed, but don't know how to stop it at the lowest/highest pressure.
It's suppose to work like this:
I have two movieclip/buttons; one for simulating more pressure, and one for less.
when the user presses the "more pressure" movieclip/button the pressure begins to rise and the arrow inside the manometer begin to turn.
At the same time as the pressure rises, another movieclip ("stamp") will push uppwards.
then another movieclip/button, "less pressure" simulates pressure drop; when pressed, the same point as the arrow stopped at when pressure rised, will start sinking towards minimum, and the stamp will go down again.
so, when the user presses "more pressure" pressure rises towards maximum, and as soon as the user stop pressing the button, the animation stops (both the stamp and the arrow). And if the user presses "lower pressure", the arrow starts sinking from where it stopped.
heres my code so far: pil1 = manometerarrow, the stamp = stamp, and "less pressure"/"more pressure" = Lpress / mpress
addEventListener (Event.ENTER_FRAME, rotate);
function rotate(event:Event):void
{
pil1.rotation = pil1.rotation+1;
}
ymutlu is on the right track. The mouse down event will only execute once when the mouse is depressed. To make the object rotate continuously while the mouse is depressed you need to increment or decrement the rotation of the object on each frame. I think the following should do the trick:
import flash.events.MouseEvent;
import flash.events.Event;
var rotate = 0;
Hpress.addEventListener(MouseEvent.MOUSE_DOWN, Hpressed);
Hpress.addEventListener(MouseEvent.MOUSE_UP, removeEnterFrame);
Lpress.addEventListener(MouseEvent.MOUSE_DOWN, Lpressed);
Lpress.addEventListener(MouseEvent.MOUSE_UP, removeEnterFrame);
function Hpressed(e:MouseEvent):void
{
rotate = 1;
addEnterFrame();
}
function Lpressed(e:MouseEvent):void
{
rotate = -1;
addEnterFrame();
}
function addEnterFrame():void
{
this.addEventListener(Event.ENTER_FRAME, update);
}
function removeEnterFrame(e:MouseEvent):void
{
this.removeEventListener(Event.ENTER_FRAME, update);
}
function update(e:Event):void
{
pil1.rotation += rotate;
}
hold to varaible that states if max button down or min button down, and check it in enterframe loop. Edited answer on your comment, hope you can sort it out.
addEventListener (Event.ENTER_FRAME, rotate);
function rotate(event:Event):void
{
if(isMaxDown) // true when max button down
pil1.rotation = Math.min(presMax,pil1.rotation+1); // presMax is max value that pressure can go
if(isMinDown) // true when min button down
pil1.rotation = Math.max(presMin,pil1.rotation-1);// presMin is min value that pressure can go
}
// isMaxDown and isMinDown are global values.
Hpress.addEventListener(MouseEvent.MOUSE_DOWN, Hpressed);
Lpress.addEventListener(MouseEvent.MOUSE_DOWN, Lpressed);
Hpress.addEventListener(MouseEvent.MOUSE_UP, H_up);
Lpress.addEventListener(MouseEvent.MOUSE_UP, L_up);
function H_up(e:MouseEvent):void {
isMaxDown=false;
}
function L_up(e:MouseEvent):void {
isMinDown=false;
}
function Hpressed(e:MouseEvent):void {
isMaxDown=true;
}
function Lpressed(e:MouseEvent):void {
isMinDown=true;
}
This code would help you but prob this is not a path to fallow to do somthing like that.