Is a simple game where a monkey throws bananas.
I want to launch the banana when the space bar is released and continue running.
When the space bar is held the banana must remain attached to the monkey until the space bar is released.
The first launch works properly, from the second onwards the bananas are not thrown correctly.
done=False
while not done:
for ev in pygame.event.get():
if ev.type == QUIT:
done = True
if ev.type ==KEYDOWN:
if ev.key== K_RIGHT:
move_right=True
if ev.key== K_LEFT:
move_left = True
if ev.key==K_SPACE:
space_down=True
still=True
elif ev.type ==KEYUP:
if ev.key== K_RIGHT:
move_right=False
if ev.key== K_LEFT:
move_left=False
if ev.key==K_SPACE:
still=False
space_down=False
launch=True
#Game logic
#move monkey
if move_right and monkey.rect.right<screen.get_width():
monkey.rect.x += 5
elif move_left and monkey.rect.left>0:
monkey.rect.x -= 5
#banana launch
if space_down:
banana=Throw_Objects()
banana.rect.midtop = monkey.rect.topright
space_down=False
if still and not space_down and move_right and monkey.rect.right < screen.get_width():
banana.rect.x += 5
if still and not space_down and move_left and monkey.rect.left > 0:
banana.rect.x -= 5
if launch:
for banana in all_object:
banana.rect.y -= 5
if banana.rect.top < 0:
banana.kill()
Any suggestions to make sure that the banana is launched when the space bar is released and when, as long as you press the space bar, the new banana will remain attached to the monkey without affecting the movement of the previous one?
Thank you
i resolded by adding a sprite group after launch in this way
if space_down:
banana=Throw_Objects()
banana.rect.midtop = monkey.rect.topright
space_down=False
if move_right and monkey.rect.right<screen.get_width():
monkey.rect.x += 5
if still:
banana.rect.x += 5
elif move_left and monkey.rect.left>0:
monkey.rect.x -= 5
if still:
banana.rect.x -= 5
if launch :
banana.rect.y -= 5
only_banana.add(banana)
launch=False
for banana in only_banana:
banana.rect.y -= 5
for banana in all_object:
if banana.rect.top < 0:
banana.kill()
I was working on adding an upgrade-like system to my game, but was having some trouble with the get_tree().get_root().get_node() thing.
In an attempt to retrieve a different node multiple layers up, I go the error
ERROR: Attempt to call function 'get_root' in base 'null instance'\ on a null instance. If I am correct, this means that it cannot find the node in the tree.
I have also tried using get_parent().get_parent()..., as well as get_node("../../../.. ...") with no luck.
Variables to get (points and pointsAdder)
extends Area2D
var points = 0.000000000001
var pointAdder = 1
var pointMultiplier = 1
var mouseover = false
var unit
var defaultArrow = load("defaultCursor_16x16.png")
var clickableCursor = load("clickableCursor.png")
func _ready():
get_parent().get_node("scoreLabel").text = "Logs: 0"
func _input(event):
if mouseover and event is InputEventMouseButton and event.pressed and event.button_index == BUTTON_LEFT:
points = (pointAdder* pointMultiplier) +points
if points < 1000:
set_label_text(points)
elif points >= 1000 and points < 1000000:
set_label_text(str(points / 1000) + " K")
unit = "thousand"
set_unit_text()
elif points >= 1000000 and points < 1000000000:
set_label_text(str(points / 1000000) + " M")
unit = "million"
set_unit_text()
elif points >= 1000000000 and points < 1000000000000:
set_label_text(str(points / 1000000000) + " B")
unit = "billion"
set_unit_text()
elif points >= 1000000000000:
set_label_text(str(points / 1000000000000) + " T")
unit = "trillion"
set_unit_text()
elif Input.is_key_pressed(KEY_SPACE) and not event.is_echo():
points = (pointAdder* pointMultiplier) +points
if points < 1000:
set_label_text(points)
elif points >= 1000 and points < 1000000:
set_label_text(str(points / 1000) + " K")
unit = "thousand"
set_unit_text()
elif points >= 1000000 and points < 1000000000:
set_label_text(str(points / 1000000) + " M")
unit = "million"
set_unit_text()
elif points >= 1000000000 and points < 1000000000000:
set_label_text(str(points / 1000000000) + " B")
unit = "billion"
set_unit_text()
elif points >= 1000000000000:
set_label_text(str(points / 1000000000000) + " T")
unit = "trillion"
set_unit_text()
func _on_Area2D_mouse_entered():
Input.set_custom_mouse_cursor(clickableCursor)
mouseover = true
func _on_Area2D_mouse_exited():
Input.set_custom_mouse_cursor(defaultArrow)
mouseover = false
func set_label_text(text_to_send):
get_parent().get_node("scoreLabel").text = ("Logs: "+str(text_to_send))
func set_unit_text():
get_parent().get_node("scoreUnitLabel").text = unit
And the code I am attempting to retrieve them in:
Extends Button
var points_cost = 10
func _on_Button_down():
if get_tree().get_root().get_node("treeClickableArea").points >= points_cost:
points_cost = (points_cost/2) + points_cost
get_tree().get_root().get_node("treeClickableArea").pointAdder = get_tree().get_root().get_node("").pointAdder + 1
get_tree().get_root().get_node("treeClickableArea").points = get_tree().get_root().get_node("treeClickableArea").points - points_cost
\Node tree:
┖╴Spatial
┠╴○ backgroundMap2
┠╴▦ backgroundMap
┠╴☺ scoreBackground
┠╴Tᵀ scoreLabel
┠╴Tᵀ scoreUnitLabel
┠╴☺ logSymbol
┠╴▭ treeClickableArea
┃ ┠╴☺ treeSprite
┃ ┖╴treeCollider
┠╴☺ upgradeBackground
┖╴▣ tabContainer
┠╴▯ perClick
┃ ┠╴perUpgradeScroll
┃ ┃ ┖╴▬ Button [scriptHavingIssuesHere]
┃ ┖╴Tᵀ Label
┖╴▯ perClickMultiplier
Could anybody clarify why I am getting this error? What exactly does it mean? Thank you for you time, I greatly appreciate any help.
Ok, another edit. I'm leaving the code from the edit I made before in case you need it for reference. I'm calling it EDIT#1.
The new example I'm posting is from a very simple test program I made. I'll call it EDIT#2.
EDIT#2 - TEST PROGRAM
Ok, so I made a simple 2D scene consisting of only a root node and 2 sprites that I named "Test1" and "Test2". I attached a script to both of the sprite nodes, each containing a variable called "points". In the first script I made points = 60,000,000, and in the second, I made points = 16. In the first script (Test1), I used onready var testNode to load the Test2 node and store it as the variable testNode. I then made a simple input event that prints the points value of the testNode variable when I press the key I assigned to "move forward". The expected result is to have the value 16 print to the console, despite both scripts containing a variable named points which each have different values (to prove i'm getting the number from the second script). For me, it works just fine. Here is the code I used for the scripts:
Node setup
-Node2d
--Test1(sprite) - script 1
--Test2(sprite) - script 2
Script 1 -
extends Sprite
var points = 60000000
onready var testNode = get_parent().get_node("Test2")
func _input(event):
if Input.is_action_just_pressed("move_forward"):
print(testNode.points)
Script 2 -
extends Sprite
var points = 16
Hopefully this stripped down example can help provide some insight into what is going on. Hope it helps.
EDIT#1 - (PREVIOUS)NEW CODE EXAMPLE - for reference
I changed the code to be more reflective of our discussion. This is how it should look in final form. Notice I changed the name of the variable treePoints to treeClickNode for clarity.
extends Button
var points_cost = 10
onready var treeClickNode = get_tree().get_root().get_node("treeClickableArea")
func _on_Button_down():
if treeClickNode.points >= points_cost:
points_cost = (points_cost/2) + points_cost
treeClickNode.pointAdder += 1
treeClickNode.points = treeClickNode.points - points_cost
I am a complete newbie and have tried solving this problem (with my own head and with online research) for the last 5 hours.
Below is a snippet of a function we have written to simulate a game. We want to offer the ooportunity to start a new round - meaning if a player hits "b", the game should start again at the beginning of the range (0, players). But right now it just goes onto the next player in the range (if player 1 enters "b", the program calls player 2)
players = input(4)
if players in range(3, 9):
for player in range(0, players):
sum_points = 0
throw_per_player_counter = 0
print("\nIt is player no.", player+1, "'s turn!\n")
print("\nPress 'return' to roll the dice.\n"
"To start a new round press 'b'.\n"
"Player", player+1)
roll_dice = input(">>> ")
if roll_dice == "b":
player = 0
throw_per_player_counter = 0
sum_points = 0
print("\n * A new round was started. * \n")
I have tried return and break, also tried to put it all in another while-loop... failed. Break and return just ended the function.
Any hints highly appreciated!
you could change the for loop to a while loop. instead of using a range, make player a counter
players = 4
if 3 <= players < 9:
player = 0 # here's where you make your counter
while player < players:
sum_points = 0
throw_per_player_counter = 0
print("\nIt is player no.", player+1, "'s turn!\n")
print("\nPress 'return' to roll the dice.\n"
"To start a new round press 'b'.\n"
"Player", player+1)
roll_dice = input(">>> ")
player += 1 # increment it
if roll_dice == "b":
player = 0 # now your reset should work
throw_per_player_counter = 0
sum_points = 0
print("\n * A new round was started. * \n")
so I have tried detecting the collision by making 2 shapes but there is some kind of mistake in it and I am wondering if there are easier ways. so this is what i tried:
cursorSurface = pygame.Surface((0,0))
cursor = pygame.draw.rect(cursorSurface, (0,0,0),(mouseX,mouseY,2,2))
mouse_mask = pygame.mask.from_surface(cursorSurface,255)
mouse_rect = cursor
if mouseAction[0] == 'move':
if mouseX > x and mouseX < xEnd and mouseY > y and mouseY < yEnd:
topTriangle = selectedSquare.subsurface(x+4,y+4,xEnd-(x+5),int((yEnd-(y+5))*0.25))
bottomTriangle = selectedSquare.subsurface(x+4,y+4+int((yEnd-(y+5))*0.75),xEnd-(x+5),int((yEnd-(y+5))*0.25))
leftTriangle = selectedSquare.subsurface(x+4,y+4,int((xEnd-(x+5))*0.25),yEnd-(y+5))
rightTriangle = selectedSquare.subsurface(x+4+int((xEnd-(x+5))*0.75),y+4,int((xEnd-(x+5))*0.25),yEnd-(y+5))
collisionTop_mask = pygame.mask.from_surface(topTriangle,255)
collisionTop_rect = topTriangle.get_rect()
collisionTop_rect.topleft = (0,0)
pygame.draw.rect(selectedSquare, colorDark,(x+5+int((xEnd-(x+5))*0.25),y+5+int((yEnd-(y+5))*0.25),int((xEnd-(x+5))*0.75)-int((xEnd-(x+5))*0.25)-2,int((yEnd-(y+5))*0.75)-int((yEnd-(y+5))*0.25)-2))
pygame.draw.polygon(topTriangle, colorDark, ((1,0), (topTriangle.get_width()-2,0), (int((xEnd-(x+7))/2),(int((yEnd-(y+7))/2)-1))))
pygame.draw.polygon(leftTriangle, colorDark, ((0,1), (0,leftTriangle.get_height()-2), (int((xEnd-(x+7))/2)-1,(int((yEnd-(y+7))/2)))))
pygame.draw.polygon(bottomTriangle, colorDark, ((1,yEnd-(y+6)-int((yEnd-(y+5))*0.75)), (bottomTriangle.get_width()-2,yEnd-(y+6)-int((yEnd-(y+5))*0.75)), (int((xEnd-(x+7))/2),(int((yEnd-(y+7))/2)+1-(yEnd-(y+5))*0.75))))
pygame.draw.polygon(rightTriangle, colorDark, ((xEnd-(x+6)-int((xEnd-(x+5))*0.75),1), (xEnd-(x+6)-int((xEnd-(x+5))*0.75),rightTriangle.get_height()-2), (int((xEnd-(x+7))/2)+1-int((xEnd-(x+5))*0.75),(int((yEnd-(y+7))/2)))))
screen.blit(selectedSquare, (0,0))
if collisionTop_mask.overlap(mouse_mask,(mouse_rect.left-collisionTop_rect.left,mouse_rect.top-collisionTop_rect.top)) != None:
print('detect')
but i have also seen this methode:
if topTriangle.get_rect().collidepoint(pygame.mouse.get_pos()):
the problem is that this only detects squares and I need to detect a triangle. could someone pleas help me with this?
You could do something like this I think (didn't test):
posx, posy = pygame.mouse.get_pos()
posx -= XCoordinateOfTopTriangleOnScreen
posy -= YCoordinateOfTopTriangleOnScreen
if topTriangle.get_at((posx,posy)) == colorDark:
print('detect')
I'm new to graphics and was wondering how I would go about creating an object boundary for my game.
Right now I have an object following my mouse. This works fine for my boundary when my ship has a rotation.z of 0. However, when I rotate the ship, the boundary has odd behavior.
I tried getting the world position of the ship and simply checking the x and y boundaries. However, the world position seems to give me a different x and y when I rotate. How can I
go about creating a boundary that works for all the rotations of my ship.
Here's my game(collisions turned off for purpose of help): http://www.cis.gvsu.edu/~chaua/CS371/WebGLProject/home.html
The behavior I'd like occurs when you don't rotate the ship.
Rotate the ship with left/right mouse.
Relevant code snippets(in render loop):
if(mouseLeftDown)
ship.rotation.z += leanSpeed;
if(mouseRightDown)
ship.rotation.z += -leanSpeed;
....
....
targetX = ((lastMouseX / window.innerWidth) * 2 - 1) * 90;
targetY = -((lastMouseY / window.innerHeight) * 2 - 1) * 60;
var worldPosition = (new THREE.Vector3()).getPositionFromMatrix(ship.matrixWorld);
if(worldPosition.x + targetX <= (randSpawnWidth/2)-500 && worldPosition.x + targetX >= -(randSpawnWidth/2)+500)
ship.translateX(targetX);
if(worldPosition.y + targetY <= (randSpawnHeight/2)-500 && worldPosition.y + targetY >= -(randSpawnHeight/2)+500)
ship.translateY(targetY);
I would appreciate any help. Thanks!