Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Puzzle 1 - Double Tap Running
#1
For all of you interested in data changing, here is a programming puzzle which I recently solved (again):

Write some code as part of the "update" function that provides double tap running behaviour for a character. It may be pseudo code, real code, or just something that is understandable.

Scenario:
To run, the user presses [left] or [right], and must release it within 10 frames of the initial keypress. After the key release, the user must press the same button again in order to run in that direction (so pressing [left] [right] doesn't make the character run right).

Info:
The update function is called every frame. You are to provide the logic that determines whether the character should go into the running sequence.
You have access to the "facingRight" variable of the character, and you can update this variable.
You have access to the left/right key states.
You can declare as many variables as you want, but it is possible to do this with just one more besides the facingRight and input variables.

Stub:
    C++-Code:
// called every time unit that the game runs
void Character::update() {
    // implement logic here
    // variables you have access to are "facingRight", input[LEFT], and input[RIGHT]
    // you may update the facingRight variable
    // you can have persistent variables that outlast this update function
 
    // e.g.
    // if (input[RIGHT] == true) {
    //     // should we run?
    // }
}


The code stub above is a highly stripped down version of what I've got, but just want to see how other people try to solve this problem. Initially I used two variables, but I managed to do it in just one.

p/s: you can ask me to clarify things, I wrote this post with a lot of contextual knowledge which you might need that I have left out.



Azriel~
Reply
Thanks given by: A-Man , Rhino.Freak
#2
Lol, what a coincidence. I just finished fixing that code for the engine I am writing (the A-Engine), and here is how I did it:
In the main loop:
http://pastebin.com/zLxzP6PK

in the Update function of the object:
http://pastebin.com/T7vCSaNA

The interval between the hold and the release is calculated time-wise, such that if I ever decided to change the FPS, it won't effect the way it works.
[Image: signature.png]
A-Engine: A new beat em up game engine inspired by LF2. Coming soon

A-Engine Dev Blog - Update #8: Timeout

Reply
Thanks given by: Rhino.Freak
#3
your code reminds me of how I used to write code before I learnt to structure code nicely (you'll learn in time, though you'd learn fastest when you code in pairs with someone who structures code nicely).

here's how I did mine:
    C++-Code:
/**
 * The number of frames elapsed since the last left/right control key press while this Character was in State::basic.
 * <p>
 * When the run counter is not started, its value is 0.
 * When the first left/right keypress is input, the counter value indicates number of frames that the key is pressed for.
 * When the left/right keypress is lifted, the counter value is negated if it is within the threshold, otherwise reset.
 * Subsequently, the counter value starts counting up.
 * When the next left/right keypress is input, if the counter has not yet reached 0, the character goes into the RUNNING sequence.
 */
int runCounter;
 
// this is an extract of the real function
void Character::doUpdate() {
	subtractFriction();
 
	if (this->runCounter != 0) {
		++this->runCounter;
	}
 
	bool movementKeyEnabled = false;
 
	if (this->inputState->isUpEnabled()) {
		movementKeyEnabled = true;
		this->vz = -this->moveSpeeds->getWalkZ();
		selectSequence(WALKING);
	} else if (this->inputState->isDownEnabled()) {
		movementKeyEnabled = true;
		this->vz = this->moveSpeeds->getWalkZ();
		selectSequence(WALKING);
	}
 
	if (this->inputState->isLeftEnabled()) {
		movementKeyEnabled = true;
		selectWalkOrRunSequence(false);
	} else if (this->inputState->isRightEnabled()) {
		movementKeyEnabled = true;
		selectWalkOrRunSequence(true);
	} else {
		// if we have started walking horizontally, but stopped walking horizontally, then we start counting "down"
		if (this->runCounter > 0) {
			this->runCounter = (this->runCounter <= RUN_COUNTER_THRESHOLD) ? -RUN_COUNTER_THRESHOLD : 0;
		}
	}
 
	if (!movementKeyEnabled) {
		selectSequence(STANDING);
	}
 
}
 
void Character::selectWalkOrRunSequence(const bool rightControlKeyPressed) {
	if ((this->facingRight == rightControlKeyPressed) && this->runCounter < 0) {
		this->vx = rightControlKeyPressed ? this->moveSpeeds->getRunX() : -this->moveSpeeds->getRunX();
		selectSequence(RUNNING);
		this->runCounter = 0;
	} else {
		this->facingRight = rightControlKeyPressed;
		this->vx = rightControlKeyPressed ? this->moveSpeeds->getWalkX() : -this->moveSpeeds->getWalkX();
		selectSequence(WALKING);
 
		// if the run counter was enabled for the opposite direction (-ve) or the character just started walking from standstill, we reset
		// the counter
		if (this->runCounter <= 0) {
			this->runCounter = 1;
		}
	}
}




Azriel~
Reply
Thanks given by: A-Man
#4
Wow! I liked how you functioned self-explanatory variable names in your code. It can all be understood just by going through the code. One thing I would like to ask is, why did you favor structs over classes?
[Image: signature.png]
A-Engine: A new beat em up game engine inspired by LF2. Coming soon

A-Engine Dev Blog - Update #8: Timeout

Reply
Thanks given by:
#5
I'm using a class there (I haven't used structs much, I'm actually not familiar with how structs work - haven't had a need to learn them).



Azriel~
Reply
Thanks given by: A-Man
#6
Oh! Never mind then. I had this random assumption that the arrow sign was only used to call variables and functions under a struct. Thanks for clarification!.
[Image: signature.png]
A-Engine: A new beat em up game engine inspired by LF2. Coming soon

A-Engine Dev Blog - Update #8: Timeout

Reply
Thanks given by:
#7
(07-27-2013, 11:02 PM)Azriel Wrote:  I'm using a class there (I haven't used structs much, I'm actually not familiar with how structs work - haven't had a need to learn them).
Off-topic but: Structs are basically the exact same thing as classes in C++. The reason why they are there is because they were a part of C, and thus also in C++ to provide C compatibility.
Everything you can do with classes you can do with structs as well, and compilers treat them as the same thing.

There is one small difference though which is simply that by default members of a class are private while members of a struct are public.

The only reason to use structs in C++ is to provide C compatibility. For example "sGame.h", which is used in both my data changer and the AI DLL, uses structs and C syntax, so it will work in both languages.
Age ratings for movies and games (and similar) have never been a good idea.
One can learn a lot from reinventing wheels.
An unsound argument is not the same as an invalid one.
volatile in C++ does not mean thread-safe.
Do not make APIs unnecessarily asynchronous.
Make C++ operator > again
Trump is an idiot.
Reply
Thanks given by:




Users browsing this thread: 1 Guest(s)