I have a shuffle button image that I'm using an an actual button. If the user 'clicks' on this image, the current song playing (if there is one) should stop playing and a random song from my list should play. If there is no song play, you would still play a random song from the list. I'm having trouble with this 'button' because the song isn't shuffling at all, infact nothing happens at all. I've used this same technique with 2 other buttons and had no problems so I think it may be the way I'm calling this method but I'm not sure what I'm doing wrong. I put in a print statement and shuffling... only prints once so I know it works but no songs are shuffling. Does anyone know what I could be doing wrong?
//Image for shuffle button
imageMode(CORNER);
image(shuffle, 140, 15, 50, 50);
void shufflePlayList() {
current=0;
tableau.shuffle();
}
//Shuffle button
if(mouseX > 140 && mouseX < 190 && mouseY > 15 && mouseY < 65){
println("shuffling...");
shufflePlayList();
}
The conditional only checks whether the mouse is within a certain area not if the button is clicked. so it will run every frame (providing it is within the draw function) if you're hovering over it
Related
I have this simple game i made in Godot Game Engine, and i have implemented some animations in my game's main character.
1. Run
This is a simple run animation i've added, which is played when the character is moving
2. Idle
This animation is more like a single image which is played when the character is not moving
3. Attack
This animation is played when user presses Left Mouse Button.
I am having my issue in attack animation, when i press Left Mouse Button my Animation doesn't play, instead i get first frame of the animation and then character goes back to idle Animation.
This is how it looks like:
This is my Character's Code:
extends KinematicBody2D
var _inputVec = Vector2.ZERO
var VELOCITY = Vector2.ZERO
var LAST_INPUT = Vector2.ZERO
const MAX_SPEED = 70
const ACCELERATION = 500
const FRICTION = 500
onready var animationPlayer = $AnimationPlayer
func _ready():
print("game started!")
func _physics_process(delta):
_inputVec.x = Input.get_action_strength("ui_right") - Input.get_action_strength("ui_left")
_inputVec.y = Input.get_action_strength("ui_down") - Input.get_action_strength("ui_up")
_inputVec = _inputVec.normalized()
if _inputVec != Vector2.ZERO:
if _inputVec.x > 0:
animationPlayer.play("playerRunRight")
elif _inputVec.y < 0:
animationPlayer.play("playerRunUp")
elif _inputVec.y > 0:
animationPlayer.play("playerRunDown")
else:
animationPlayer.play("playerRunLeft")
VELOCITY = VELOCITY.move_toward(_inputVec * MAX_SPEED, ACCELERATION * delta)
LAST_INPUT = _inputVec
else:
VELOCITY = VELOCITY.move_toward(Vector2.ZERO, FRICTION * delta)
if Input.is_action_just_pressed("ui_lmb"):
if LAST_INPUT.x > 0:
animationPlayer.play("playerAttackRight")
elif LAST_INPUT.y < 0:
animationPlayer.play("playerAttackUp")
elif LAST_INPUT.y > 0:
animationPlayer.play("playerAttackDown")
else:
animationPlayer.play("playerAttackLeft")
else:
if LAST_INPUT.x > 0:
animationPlayer.play("playerIdleRight")
elif LAST_INPUT.y < 0:
animationPlayer.play("playerIdleUp")
elif LAST_INPUT.y > 0:
animationPlayer.play("playerIdleDown")
else:
animationPlayer.play("playerIdleLeft")
VELOCITY = move_and_slide(VELOCITY)
Full Project is Available at my Github Repo
Remember that _physics_process runs once per (physics) frame.
So, one frame you pressed the left mouse button, and this line got to execute:
animationPlayer.play("playerAttackRight")
But next (physics) frame, you had not just pressed the left mouse button, so this conditional is false:
if Input.is_action_just_pressed("ui_lmb"):
And then this line get to execute:
animationPlayer.play("playerIdleRight")
As a result, you only see about one frame of the "playerAttackRight" animation.
You are going to need to keep track of the current state (running, attacking, idle). The rule is that you can change from running to idle immediately, but you can only change from attacking to idle, when the attack animation ends.
You can keep track of the current state with a variable, of course. You can take input and the value of the state of the variable to decide the new state. Then separately read the state variable and decide which animation to play. You may also want to set the state variable when some animations end.
And to do something when an animation ends, you can either resource to yield:
yield(animationPlayer, "animation_finished")
Which will have your code resume after it receives the "animation_finished" signal.
Or, otherwise you can connect to the "animation_finished" signal.
By the way, you can also queue animations:
animationPlayer.queue("name_of_some_animation")
While using AnimationPlayer like you do is OK. When it gets complex, there is another tool you should consider: AnimationTree.
Create an AnimationTree node, give it your animation player, and set the root to a new AnimationNodeStateMachine. There you can create your state machine, and configure if the transition between them is immediate or at the end.
Then, from code, you can get the state machine playback object, like this:
var state_machine = $AnimationTree.get("parameters/playback")
You can ask it what the current state is with:
var state:String = state_machine.get_current_node()
Which you can use as part of the decision of which state you want to go to. And then tell it you want it to go to a different state, like this:
state_machine.travel("name_of_some_state")
And using that it will respect the transitions you set, so you do not have to worry about it in code.
You can find more information about using AnimationTree at:
Using AnimationTree
Controlling Animation States
Looking around in the forum. Finally, I decided to join in this big community for the support it provides!
I am creating this post because I am struggling in a 2D game that I am creating in Unity.
The game keeps scoring the number one once the play button is clicked. It increases the score once the food is collected, but the problem here is that once I click on "Play" button the score is already on "1" instead of "0".
Code in the following statement:
Scoring System
Collect C#
Thank you for your help!
You could do 2 things:
Add a Start() function in Scoring System script.
private void Start(){
// This would make sure that score is 0 from the first frame
scoreText.GetComponent<Text>().text = " " + 0;
}
2)Instead of directly running the code on trigger use tags, assign the tag of Player to your player gameObject, then add this code.
void OnTriggerEnter2D(Collider2D collision)
{
if(collision.tag == "Player"){
ScoringSystem.theScore += 1;
// Destroy(collision.gameObject);
}
}
I have a task on Unity 3d that if the player doesn't move for 5 seconds, a pop-up shows on the center of the screen and if the player moves, the pop-up disappears. How can I write the logic for this task please ?
Thanks
Here is code that will check the mouse position of the user and see if it has moved in the last 5 seconds. If it has not, then the popup window will show up. If it's hard to read here with the comments (I kind of think it is) copy and paste this code into Visual Studio so the colors will help distinguish code from comments.
[SerializeField] GameObject popupWindow = null;
float totTime;
float timeBeforePause = 5f;
Vector3 updatedMousePosition;
private void Update()
{
// Add the time delta between frames to the totTime var
totTime += Time.deltaTime;
// Check to see if the current mouse position input is equivalent to updateMousePosition from the previous update
// If they are equivalent, this means that the user hasn't moved the mouse
if (Input.mousePosition == updatedMousePosition)
{
// Since the user hasn't moved the mouse, check to see if the total Time is greater than the timeBeforePause
if (totTime >= timeBeforePause)
{
// Set the popup window to true in order to show the window (instantiate instead it if if doesn't exist already)
popupWindow.SetActive(true);
}
}
// If the user has moved the mouse, set the totTime back to 0 in order to restart the totTime tracking variable
else
{
totTime = 0;
}
// Check to see if the popup window is visible (active)
if (popupWindow.activeSelf == true)
{
// Check to see if the user has pressed the Esc button
if (Input.GetKeyDown(KeyCode.Escape))
{
// Hide the window
popupWindow.SetActive(false);
}
}
// Update the updatedMousePosition before the next frame/update loop executes
updatedMousePosition = Input.mousePosition;
}
If you want to track different user input (key presses) you can use a similar method. Also you will have to implement some sort of button on the popup window that will allow the user to exit out from the popup window once they return. Hope this helps!
I have this sprite: spr_meteoriteLv3, which has two sub-images with index image_index 0 and 1 respectively.
I have these objects: obj_meteoriteLv3, obj_tempMeteoriteLv3, and obj_score. Object obj_meteoriteLv3 spawns from above with random position, random amount, and random sub-image. Object obj_tempMeteoriteLv3 makes obj_meteoriteLv3s spawn. When player clicks on a meteorite, the program checks the value of image_index for that object.
obj_meteoriteLv3 has these events:
Create Event: change sprite_index into spr_meteoriteLv3, and start moving downwards.
Left-pressed Mouse Event: destroy the self instance, and check image_index: if image_index == 0 then score += 5; else score -= 5).
obj_tempMeteoriteLv3 has these events:
Create Event: set Alarm 0 to 3600, set variable exist to 1, and set variable add to 1.
Alarm 0: set variable add to 0, and destroy the obj_meteoriteLv3 instance.
Alarm 1: set variable exist to 1.
Step Event: if (exist == 1) then, if (add == 1) then create instance of obj_meteoriteLv3, set variable exist to 0, and set Alarm 1 to 10.
obj_score has these events:
Create Event: set score to 0.
Draw Event: draw the value of score.
The problem is, no matter which sub-image the meteorite image_index has when clicked, the score will always be incremented by 5 points. It's like the else condition isn't working. How can I fix this? Please explain your answer. Thanks.
I add some images for better understanding. Link 1. Link 2
In obj_meteoriteLv3 it's being destroyed before it can execute the rest of the code blocks. Move "Destroy Instance" to the bottom.
In obj_tempMeteoriteLv3 both variables "add" and "exist" are not necessary, instead have-
Create Event-
alarm[0] = 3600
alarm[1] = 10
Alarm[0] Event-
destroy_instance
Alarm[1] Event
Create_instance of obj_meteoriteLv3
alarm[1] = 10
Potentially, when you click, every single meteorite is triggered.
On the left click event of the meteorite, you did not check if the cursor was on the sprite. You have to use the position_meeting function, to which you pass the mouse position and the instance to click.
it would look like :
if (position_meeting(mouse_x, mouse_y, id))
{
//your destroy code
}
Moreover, when the instance_destroy(); line is read, the following code is ignored and the program jumps to the destroy_event. William explained it well and suggested to change the order of the lines of code, but you can also change the score in the destroy event directly.
I would like to add that checking for clicks in every instance of the meteorites is not optimal for performances.
My recommendation would be to use a single object to check for clicks (your player or your meteorite spawner, for example), in which you would check for clicks, and if a meteorite is touched, you would trigger it's destroy event. And in this event, you would increment the score and check the sprite.
Your click event would look like :
with (instance_position(mouse_x, mouse_y, obj_meteoriteLv3))
{
instance_destroy();
}
and in the meteorite destroy event, you would check the image_index and change the score accordingly.
EDIT : why the score doesn't change
I believe you didn't declare the score as a global variable, but as an instance variable. So when you write "score = ..." in an other object, it creates a new score variable, unrelated to the precedent.
You have 2 options :
1 - Declare the score a global variable in the create event of obj_score:
globalvar score;
score = //your starting score
Be aware that a global variable can't be set on it's initialisation line.
2 - Change the score through the score object :
whenever the score has to change :
obj_score.score = ...
I have the following JS function, which I'm using to detect whether a 'draggable' image on my HTML5 canvas is dragged on top of a static 'description box' image, also displayed on the canvas:
function isHit(mouseX, mouseY){
if(draggingImage == true){
console.log("if dragging image == true statment is being called");
if(mouseY > 420){
if((mouseX > 80) && (mouseX < 200) && (obj.shape.index >= 0) && (obj.shape.index <= numImagesAssets)){
console.log("Correct");
}else{
console.log("Incorrect");
}
}
}
}
The idea is that there will be a number of static images on the canvas (which will be the description boxes), and a greater number of draggable images. The user will be required to drag each of the draggable images to the relevant description box.
At the moment, my if statement is just checking to see whether the image currently being dragged belongs in the first of four description boxes.
Since the description boxes are all displayed in a row towards the bottom of the canvas, I've set my function to only check for a collision when the mouseY variable (y position of the cursor on the canvas) is greater than 420- since 420 is the top 'boundary' of the description box images.
Then, if the draggingImage variable is true, and the cursor's mouseY value is greater than 420, I want to start checking whether the cursor hovers over any of the description boxes. The first one is displayed between the X positions 80 and 200, so I'm checking if mouseX is greater than 80 and less than 200.
If it is, the function should then check whether the value of obj.shape.index is greater than or equal to 0 and less than the value of numImagesAssets. If it is, the console should log "correct", and if not, it should log "incorrect".
The variable obj.shape.index gets the position of the image that has been clicked in my array of images (this array contains all of the draggable images displayed on the canvas). If value of that is between a certain range, then I know that the image belongs to the first description box, if it's between another range, it belongs to the next description box, etc.
In this example, the value of the variable numImagesAssets is 10 (as displayed in the console by a console.log line in my code)
In my mousedown function, I have the line:
console.log("value of variable obj:" + output + ". Shape is " + obj.shape + ". index is " + obj.shape.index);
and when I click on an image on my canvas, this console.log line displays the value of the variable property obj.shape.index, for example, I just clicked on one of the draggable images on the canvas, and this line printed the following output to the console:
value of variable obj:shape: [object Object]; pixel: [object Uint8ClampedArray]; . Shape is [object Object]. index is 8
So I know that the image I clicked that time was at position 8 in my images array (I've checked this manually several times, clicking a different image each time, and it was always displaying the correct position).
Now, the problem I'm having, is that when I actually go and drag an image over its correct description box, I get a console error that says "obj is not defined", and it's complaining about the line:
if((mouseX > 80) && (mouseX < 200) && (obj.shape.index >= 0) && (obj.shape.index <= numImagesAssets)){
But, strangely, if I drag an image to one of the description boxes it doesn't belong to, the else clause in my if statment is triggered correctly, and the word "Incorrect" is printed to the console....
I can't figure out why it's not working when I drag an image to the correct description box, or why it says that "obj" is not defined in that case, but then is happy to use "obj" for the 'else' clause in the if statement.
Anyone have any ideas?
Edit 19/03/2013 # 12:00
Ok, I've edited my isHit function a little, to add another console.log line which will show the value of obj.shape.index within my isHit function. The function now looks like this:
function isHit(mouseX, mouseY, obj){
if(draggingImage == true){
console.log("if dragging image == true statment is being called");
if(mouseY > 420){
console.log("Value of obj.shape.index = " +obj.shape.index);
if((mouseX > 80) && (mouseX < 200) && (obj.shape.index >= 0) && (obj.shape.index <= numImagesAssets)){
console.log("Correct");
}else{
console.log("Incorrect");
}
}
}
}
I have the following console log line just before the call to isHit:
console.log("obj.shape.index = " + obj.shape.index);
This line displays that the value of obj.shape.index is 0 when I first click on the image (which is correct- it is the first image in my array of images), however, as I then drag the image around the canvas, the value of obj.shape.index seem to increase randomly... at one point the console was displaying that it was 23, then that it was 25, and then when I finally drag it to its description box, the console logs the line:
if dragging image == true statment is being called
showing that the isHit function is being called, and the next thing printed to the console is the line:
Value of obj.shape.index = 34
Any idea why the value of obj.shape.index keeps increasing? Is it not actually the position of the element within the array? I'm sure it is though, because when I click on one of the other images, it displays the value of their position within the array, so I don't understand why the value keeps increasing as I move the image around the canvas... it's position within the array isn't being altered at all...
If obj.shape.index is valid before entering isHit(), you probably have a scoping issue.
Try this -- supply obj to isHit:
// call isHit and also supply obj
console.log("obj = "+obj); // Test obj for validity just before calling isHit
var isItHit = isHit(mouseX, mouseY, obj); // Then call isHit WITH obj
// and modify isHit to accept the obj
function isHit(mouseX,mouseY,obj) { ...