I'm trying to build a ping pong game with Processing language. For this two-player game I have two controllers at each end of the 'table'. I coded the movements of the players (up and down) by binding them to the keys:
- w and s for player 1
- o and l for player 2
Although this works when I press them one at a time, I cannot figure out how to make them move simultaneously, as in pressing both w and o at the same time.
Here is my code:
int x=535;
int y=350;
int dx=5;
int dy=5;
int pX=10;
int pY=520;
int pX1=1870;
int pY1=520;
int pS=5;
void setup() {
size(1920,1080);
}
void draw() {
background(0);
rect(960,0,5,1080);
rect(pX,pY,40,150);
rect(pX1,pY1,40,150);
ellipse(x,y,50,50);
x=x+dx;
y=y+dy;
bounce();
move();
move1();
}
void bounce(){
if(x>=1920 || x<=0){
dx=-dx;
}
if(y>1080 || y<0){
dy=-dy;
}
}
void move(){
if(keyPressed){
if(key == 's'){
pY+=pS;
}else if (key == 'w'){
pY-=pS;
}
}
}
void move1() {
if(keyPressed){
if(key == 'l'){
pY1+=pS;
}else if (key == 'o'){
pY1-=pS;
}
}
}
What you want to do is create a boolean value for each key you care about. Then in the keyPressed() function, you set the corresponding variable to true, and in the keyReleased() function, you set the corresponding variable to false. Then in your draw() function, you check the variables to determine which keys are pressed.
Shameless self-promotion: I wrote a tutorial on getting user input available here. Check out the Handling Multiple Keys section.
Related
I am making a platformer game where you have to dodge spikes, and I tried to use the transform.position method, but it gave too many bugs. With rigidbodies(rb.addforce), it has acceleration, and I saw somewhere that you could use getaxisraw to do it. Is there any way that I could add this to my current script without deviating too much (still being able to use wasd and arrow keys)?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class playerscript : MonoBehaviour
{
public float movespeed = 0.01f;
public Rigidbody2D rb;
public bool isgrounded = true;
public float jumpheight = 500f;
public float level = 1;
// Start is called before the first frame update
void Start()
{
rb = this.gameObject.GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void FixedUpdate()
{
if (Input.GetKey(KeyCode.A) || (Input.GetKey(KeyCode.LeftArrow)))
{
rb.AddForce(-Vector2.right * movespeed);
}
if (Input.GetKey(KeyCode.W) && isgrounded || (Input.GetKey(KeyCode.UpArrow) && isgrounded))
{
rb.AddForce(transform.up * jumpheight);
isgrounded = false;
}
if (Input.GetKey(KeyCode.D)||(Input.GetKey(KeyCode.RightArrow)))
{
rb.AddForce(Vector2.right * movespeed);
}
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.tag == "enemy")
{
Debug.Log("hio");
if (level == 1)
{
Debug.Log("resetpos");
transform.position = new Vector3((float)-11.343, (float)-0.49, 0);
}
}
}
private void OnCollisionStay2D(Collision2D collision)
{
if (collision.gameObject.tag == "ground")
{
isgrounded = true;
}
}
}
From https://docs.unity3d.com/ScriptReference/Input.GetAxisRaw.html, I think that Input.GetAxisRaw("Horizontal") will return -1 if the user presses in left or a, 0 if the user is not pressing left or right or a or d, and 1 if the user presses right or d. Similarly, this also occurs for Input.GetAxisRaw("Vertical"). I think it will return -1 if the user wants to go down, 0 if the user is not pressing up or down, and 1 if the user wants to go up.
In FixedUpdate(), you can get Input.GetAxisRaw("Horizontal") to get whether they want to move right or left, and Input.GetAxisRaw("Vertical") to get whether they want to move down or up. Then, you can handle it by moving the character appropriately.
For example, you can do this:
void FixedUpdate()
{
if (Input.GetAxisRaw("Horizontal") == -1)
{
// Code to move left
}
else if (Input.GetAxisRaw("Horizontal") == 1) {
// Code to move right
}
if (Input.GetAxisRaw("Vertical") == -1)
{
// Code to move down or squat
}
else if (Input.GetAxisRaw("Vertical") == 1)
{
// Code to move up or jump
}
}
Please excuse me if I made any C# syntax errors.
I have a function (lets call it function A) that 0 to many threads can access it (at the same time, no shared resources). At any given time, the user can use to stop the process. The stop functionality needs to make sure that there are threads accessing function A, so that a graceful shutdown can be performed. Is there a native procedure to do so?
What I was going to do is have an InterlockedIncrement an integer everytime function A is called (and a corresponding InterlockedDecrement on said integer when function A exists). When an InterlockedDecrement takes place, it checks the value of the integer, if it's set to zero, a event is set to signalled. If the value is not zero, the event is set to nonsignalled.
This makes sense in my mind, but I'm curious whether there is a more native structure / functionality adapted to do so.
I still have to thing about the fact the "stop" function may get starved (in the sense, the said integer may never be set to zero). A sidenote: when the stop event takes place, the InterlockedIncrement process shall be stopped, to reduce said starvation.
what you need and want implement is called Run-Down Protection. unfortunately it supported only in kernel mode, but not hard implement it yourself in user mode too.
the simplest implementation is next:
HANDLE ghStopEvent;
LONG gLockCount = 1;
BOOLEAN bStop = FALSE;
void unlock()
{
if (!InterlockedDecrement(&gLockCount)) SetEvent(ghStopEvent);
}
BOOL lock()
{
LONG Value = gLockCount, NewValue;
for ( ; !bStop && Value; Value = NewValue)
{
NewValue = InterlockedCompareExchange(&gLockCount, Value + 1, Value);
if (NewValue == Value) return TRUE;
}
return FALSE;
}
void funcA();
void UseA()
{
if (lock())
{
funcA();
unlock();
}
}
and when you want begin rundown - once call
bStop = TRUE; unlock();
how you can see lock function is interlocked increment gLockCount on 1 but only if it not 0.
in kernel mode you can call instead
EX_RUNDOWN_REF gRunRef;
void UseA()
{
if (ExAcquireRundownProtection(&gRunRef))
{
funcA();
ExReleaseRundownProtection(&gRunRef)
}
}
and on place final unlock - ExWaitForRundownProtectionRelease
some more complex and scalable implementation of rundown-protection:
#define RUNDOWN_INIT_VALUE 0x80000000
#define RUNDOWN_COMPLETE_VALUE 0
class __declspec(novtable) RUNDOWN_REF
{
LONG _LockCount;
protected:
virtual void RundownCompleted() = 0;
public:
BOOL IsRundownBegin()
{
return 0 <= _LockCount;
}
void Reinit()
{
if (InterlockedCompareExchange(&_LockCount, RUNDOWN_INIT_VALUE, RUNDOWN_COMPLETE_VALUE) != RUNDOWN_COMPLETE_VALUE)
{
__debugbreak();
}
}
RUNDOWN_REF()
{
_LockCount = RUNDOWN_INIT_VALUE;
}
BOOL AcquireRundownProtection()
{
LONG Value = _LockCount, NewValue;
for ( ; Value < 0; Value = NewValue)
{
NewValue = InterlockedCompareExchange(&_LockCount, Value + 1, Value);
if (NewValue == Value) return TRUE;
}
return FALSE;
}
void ReleaseRundownProtection()
{
if (RUNDOWN_COMPLETE_VALUE == InterlockedDecrement(&_LockCount))
{
RundownCompleted();
}
}
void BeginRundown()
{
if (AcquireRundownProtection())
{
_interlockedbittestandreset(&_LockCount, 31);
ReleaseRundownProtection();
}
}
};
and use it like:
class MY_RUNDOWN_REF : public RUNDOWN_REF
{
HANDLE _hEvent;
virtual void RundownCompleted()
{
SetEvent(_hEvent);
}
// ...
} gRunRef;
void UseA()
{
if (gRunRef.AcquireRundownProtection())
{
funcA();
gRunRef.ReleaseRundownProtection();
}
}
and when you want stop:
gRunRef.BeginRundown();// can be safe called multiple times
// wait on gRunRef._hEvent here
interesting that in kernel exist else one (more old - from win2000, when rundown protection from xp) api Remove Locks. it do almost the same. different only in internal implementation and usage. with remove locks code will be look like this:
IO_REMOVE_LOCK gLock;
void UseA()
{
if (0 <= IoAcquireRemoveLock(&gLock, 0))
{
funcA();
IoReleaseRemoveLock(&gLock, 0);
}
}
and when we want stop - call
IoAcquireRemoveLock(&gLock, 0);
IoReleaseRemoveLockAndWait(&gLock, 0);
my first code spinet by implementation near remove locks implementation, when second near rundown-protection implementation. but by sense both do the same
I'm trying to implement a pause/play for a sketch with the same key, for example if I press p the sketch should stop and if I press p again, the sketch should start again. So far I used the noLoop()/loop() to do this but with two different keys (p for pause, r for start). It does work if I use keyPressed() and keyReleased() but this means to hold down the key but this doesn't answer my question. Also in the pause mode I used redraw() for a single step while noLoop() and works good.
Here is some code I tried so far with two different keys:
public void draw(){
background(random(255));
}
public void keyPressed(){
if ( key == 'p' )
noLoop();
if ( key == 'r' )
loop();
if ( key == 's' )
redraw();
}
And this is the code with the same key:
public void draw(){
background(random(255));
}
public void keyPressed(){
if ( key == 'p' )
noLoop();
if ( key == 'p' )
loop();
if ( key == 's' )
redraw();
}
In this case when I press key it doesn't have any effect.
And the last one I tried is this:
public void draw(){
background(random(255));
}
public void keyPressed(){
if ( key == 'p' )
noLoop();
else
loop();
if ( key == 's' )
redraw();
}
In this case when I press 'p' it stops the sketch but is doesn't play again. Because of the 'else' it plays again when I press any key including 's' which suppose to be just for a single step.
Any help is more than welcome.
Thanks!
Please try to post a MCVE that we can copy and paste to run ourselves. The code you've posted is almost a MCVE, but please include a draw() function so we can see exactly the same thing as you.
Here's a simple MCVE that demonstrates the problem you're having:
void draw() {
background(random(255));
}
public void keyPressed() {
if ( key == 'p' ) {
noLoop();
}
if ( key == 'p' ) {
loop();
}
}
This code will show a randomly flashing background. If you press the P key, you're expecting it to pause, but it just keeps flashing.
You need to get into the habit of stepping through your code to understand exactly what it's doing. Read through the keyPressed() function line by line, and imagine what the code will do when you press the P key.
The first if statement checks whether the key is P, and since it is, it calls the noLoop() function. Then the second if statement checks whether they key is P, and since it is, it calls the loop() function. This reverses the call to noLoop() we just made, which makes it appear as though nothing happens.
You need to track the state of your sketch. In your case, you need to track whether the sketch is currently paused. You could use a single boolean variable for this. Then use that variable to make sure you do the right thing when the P key is pressed. Something like this:
boolean paused = false;
void draw() {
background(random(255));
}
public void keyPressed() {
if ( key == 'p' ) {
paused = !paused;
if (paused) {
noLoop();
} else {
loop();
}
}
}
I'm using Processing 3.0.1 which is the latest version.
I successed to display the image when I pressed a certain key.
For example, when I press key 'a', then the image will be displayed.
I also want to make the image disappear when I press another key.
However, I can't find a way to do this.
If anyone knows how to do this, please help me
Here is the code
PImage Onepiece1, Onepiece2;
void setup(){
size(600,600);
Onepiece1 = loadImage("Onepiece1.jpg");
Onepiece2 = loadImage("Onepiece2.jpg");
}
void draw(){
}
void showimage1(){
image(Onepiece1,10,10);
}
void keyPressed(){
if(key == 'a'){
showimage1();
}
else if(key == 'b'){
// I want to make the image disappear when I press 'b'
}
println(key);
}
For this simple scenario #Majlik suggestion is ok, but usually it's not a good idea to draw in callback functions like keyPressed(). Instead use a flag to drive drawings in draw(), like:
Untested
PImage Onepiece1, Onepiece2;
boolean showimage = false;
void setup(){
size(600,600);
Onepiece1 = loadImage("Onepiece1.jpg");
Onepiece2 = loadImage("Onepiece2.jpg");
background (255);
}
void draw(){
background (255);
if(showImage){
showImage1();
}
}
void showimage1(){
image(Onepiece1,10,10);
}
void keyPressed(){
if(key == 'a'){
showImage = true;
}
else if(key == 'b'){
showImage = false;
}
println(key);
}
For the simple scenario like this you just need to redraw image with anything. Best practice is to use background() function. So your reaction to pressing b could look like:
if(key == 'b'){
background(99);
}
Also it is good practice to have specified same background color at the beginning inside setup() function:
void setup(){
size(600,600);
...
background(99);
}
Hello everyone I have been following this tutorial here http://www.gogo-robot.com/2011/05/30/xna-skinned-model-animations/ and so far its great got the animations playing and everything, but now I want to expand it and stop the continuous loops say for instance i press the a key to make the model jump when i release the a key i want him to stop jumping but if i hold the a key i want him to keep jumping. Here what i have tried so far
and none of it works.
I am stumped here on how to do this thanks for any help with this.
private void HandleInput(GameTime gameTime)
{
currentGamePadState = GamePad.GetState(PlayerIndex.One);
// Check for changing anims
//SkinningData skinningData = model.Tag as SkinningData;
SkinningData sd = jumper.model.Tag as SkinningData;
if (currentGamePadState.Buttons.A == ButtonState.Pressed)
{
if (jumper.animationPlayer.CurrentClip.Name != "Fire")
jumper.animationPlayer.StartClip(sd.AnimationClips["Fire"]);
}
if (currentGamePadState.Buttons.X == ButtonState.Pressed)
{
if (jumper.animationPlayer.CurrentClip.Name != "DieF")
jumper.animationPlayer.StartClip(sd.AnimationClips["DieF"]);
}
//does not work
if (currentGamePadState.Buttons.X == ButtonState.Released)
{
if (jumper.animationPlayer.CurrentClip.Name == "DieF")
jumper.animationPlayer.StartClip(sd.AnimationClips["Idel"]);
}
if (currentGamePadState.Buttons.Y == ButtonState.Pressed)
{
if (jumper.animationPlayer.CurrentClip.Name != "Idel")
jumper.animationPlayer.StartClip(sd.AnimationClips["Idle"]);
}
//does not work
if (jumper.animationPlayer.CurrentTime == jumper.animationPlayer.CurrentClip.Duration)
{
//set him back to idel
jumper.animationPlayer.StartClip(sd.AnimationClips["Idle"]);
}
I have tried these configuration with no luck in the game
// Starts playing the entirety of the given clip
public void StartClip(string clip, bool loop)
{
AnimationClip clipVal = skinningData.AnimationClips[clip];
StartClip(clip, TimeSpan.FromSeconds(0), clipVal.Duration, loop);
}
// Plays a specific portion of the given clip, from one frame
// index to another
public void StartClip(string clip, int startFrame, int endFrame, bool loop)
{
AnimationClip clipVal = skinningData.AnimationClips[clip];
StartClip(clip, clipVal.Keyframes[startFrame].Time,
clipVal.Keyframes[endFrame].Time, loop);
}
// Plays a specific portion of the given clip, from one time
// to another
public void StartClip(string clip, TimeSpan StartTime, TimeSpan EndTime, bool loop)
{
CurrentClip = skinningData.AnimationClips[clip];
currentTime = TimeSpan.FromSeconds(0);
currentKeyframe = 0;
Done = false;
this.startTime = StartTime;
this.endTime = EndTime;
this.loop = loop;
// Copy the bind pose to the bone transforms array to reset the animation
skinningData.BindPose.CopyTo(BoneTransforms, 0);
}
Can you not attach a bool on the animation clip to tell it to play only once, or an active variable that can be called.