Move an image using a spritesheet in an if statement - animation

I have a beaver that is meant to follow the user frog. It moves in the direction of the frog at a slower pace. However I want the beaver to have a left and right animation. So I have the movement working, just not the animation.
local BidoofSheetData =
{
width = 32,
height = 48,
numFrames = 8,
sheetContentWidth = 128,
sheetcontentheight = 96
}
--Set File Actual size
bidoofSheet = graphics.newImageSheet ("BidoofSpriteSheet.png", BidoofSheetData)
--Set the sequences
local bidoofsequenceData = {
{name = "bstop", start = 1, count = 1, time = 300},
{name = "bleft", start = 2, count = 3, time = 300},
{name = "bright", start = 5, count = 3, time = 300}
}
--frog mask
local physicsData = (require "bidoofdefs").physicsData(1.0)
--Link sheet data to previous settings
beaver = display.newSprite(bidoofSheet, bidoofsequenceData)
beaver.x = display.contentWidth/2
beaver.y = 284
physics.addBody( beaver, "static")
beaver.isFixedRotation = true
--
function moveBeaver ()
if frog.x > beaver.x then
beaver.x = beaver.x + 0.5
elseif frog.x < beaver.x then
beaver.x = beaver.x - 0.5
elseif frog.x == beaver.x then
beaver.x = beaver.x
end
end
Runtime:addEventListener("enterFrame", moveBeaver)
I've tried to add it in the moveBeaver function, but it doesn't work.
EDIT:
i tried adding beaver:setSequence("bleft");beaver:play() into the different areas. it played one frame for left and one for right if you move in the respective directions. if you move to far left or right and stopped, it would play both left and right frames constantly.
but it didn't play the 3 frame animation i want it to.

First off, I noticed an inconsistency in your sheet data.
local BidoofSheetData =
{
width = 32,
height = 48,
numFrames = 8,
sheetContentWidth = 128,
sheetcontentheight = 96 -- Shouldn't this be sheetContentHeight ?
}
I'm not sure if having the proper capitalization of sheetContentHeight matters, but I thought I'd bring it up. I think I know what the issue is with your animation now. You were setting it to play any time the beaver needed to move, which would reset it to the first frame of the animation.
Try this instead:
function updateAnim(who, seq)
if who.sequence == seq then
-- We're already animating the way we need to be.
return
end
who:setSequence(seq)
who:play()
end
function moveBeaver()
-- Get the distance from beaver to frog's position.
local d = frog.x - beaver.x
-- This will allow the beaver to stop precisely on the frog's position,
-- without exceeding a distance of +/- 0.5 per move.
if d == 0 then
updateAnim(beaver, "bstop")
elseif d > 0 then
beaver.x = beaver.x + math.min(d, 0.5)
updateAnim(beaver, "bright")
else
beaver.x = beaver.x + math.max(d, -0.5)
updateAnim(beaver, "bleft")
end
end

Related

How do I select a line by clicking in Makie?

I want to be able to select a line on the plot by clicking on it. Ideally, when I click on any line, the number of that line will appear on the screen.
I wrote my code based on the tutorial, but there is no example with lines, so I did what I did. https://docs.makie.org/v0.19/documentation/events/index.html#point_picking
At the moment I have no idea what these numbers are telling me and why. They are not even coordinates of clicked points.
P.S. Actually it is just a starting point. I want to create event interaction on series and topoplots. But for now it would be great to find out the basics.
f = Figure(backgroundcolor = RGBf(0.98, 0.98, 0.98), resolution = (1500, 700))
ax = Axis(f[1, 1], xlabel = "Time [s]", ylabel = "Voltage amplitude [µV]")
N = 1:length(pos)
positions = Observable(rand(Point2f, 10))
xs = 0:0.01:10
ys = 0.5 .* sin.(xs)
lines!(xs, ys)
lines!(xs, ys * 2)
hidedecorations!(ax, label = false, ticks = false, ticklabels = false)
hidespines!(ax, :t, :r)
hlines!(0, color = :gray, linewidth = 1)
vlines!(0, color = :gray, linewidth = 1)
i = Observable(0)
on(events(f).mousebutton, priority = 2) do event
if event.button == Mouse.left && event.action == Mouse.press
plt, i[] = pick(f)
str = lift(i -> "$(i)", i)
text!(ax, 1, -0.5, text = str, align = (:center, :center))
end
end
f
Below are some examples of the interaction between clicking and the number displayed (the red dot is where I click).
Check out the mouseposition variable here:
https://docs.makie.org/stable/api/#Events
or the registerInteraction! function here:
https://docs.makie.org/v0.19/examples/blocks/axis/index.html#registering_and_deregistering_interactions
You can use them both as below:
using GLMakie
f = Figure(backgroundcolor = RGBf(0.98, 0.98, 0.98), resolution = (1500, 700))
ax = Axis(f[1, 1], xlabel = "Time [s]", ylabel = "Voltage amplitude [µV]")
#N = 1:length(pos)
positions = Observable(rand(Point2f, 10))
xs = 0:0.01:10
ys = 0.5 .* sin.(xs)
lines!(xs, ys)
lines!(xs, ys * 2)
hidedecorations!(ax, label = false, ticks = false, ticklabels = false)
hidespines!(ax, :t, :r)
hlines!(0, color = :gray, linewidth = 1)
vlines!(0, color = :gray, linewidth = 1)
register_interaction!(ax, :my_interaction) do event, axis
if event.type === MouseEventTypes.leftclick
println("Graph axis position: $(event.data)")
end
end
i = Observable(0)
on(events(f).mousebutton, priority = 2) do event
if event.button == Mouse.left && event.action == Mouse.press
plt, i[] = pick(f)
str = lift(i -> "$(i)", i)
text!(ax, 1, -0.5, text = str, align = (:center, :center))
#show mouseposition(f)
end
end
f
Note that for some reason (perhaps it sees the first click as a selection?) Makie does not start registering the interaction on the graph until the first click within the graph, unlike the clicks on the figure which are all shown even the first one.

Yaw rotation of gear object in vpython

I was wondering how to yaw gear object about Y-axis in vpython. I have been following some tutorials and I have managed to rotate the gear. The gear rotates about Z axis in vpython. I want the gear to remain rotating about Z axis but I would like to yaw the gear around Y-axis. When xxx.rotate(axis=vector(0,0,1), it works as it should do. As soon as I alter anything it goes crazy. I am not sure what xxx.rotate(origin) is meant to do. In my case, I have messed around with the origin vector but it doesn't make any sense to me. I am not sure if the origin vector expects parameter values in x,y,z or some other sequence. I hope I am making makes sense.
The code below is a working code and you can see what I am trying to do here. I have been debugging for a while so please ignore unnecessary comments.
'
# https://www.youtube.com/watch?v=0Sw8sxsN984
# https://www.youtube.com/watch?v=MJiVtz4Uj7M
from vpython import *
import numpy as np
axisOpac = 0.4
def makeAxes(length):
global axes
xaxis = arrow(pos=vector(0, 0, 0), axis=length*vector(1,0,0), shaftwidth = 0.1*(length), color=color.red, opacity = axisOpac)
negXaxis = xaxis.clone()
negXaxis.axis *= -1
yaxis = arrow(pos=vector(0, 0, 0), axis=length*vector(0,1,0), color=color.green, opacity = axisOpac)
negYaxis = yaxis.clone()
negYaxis.axis *= -1
zaxis = arrow(pos=vector(0, 0, 0), axis=length*vector(0,0,1), color=color.magenta, opacity = axisOpac)
negZaxis = zaxis.clone()
negZaxis.axis *= -1
fudge = 0.01*length
xlabel = label(text = "x", color = xaxis.color, pos=xaxis.axis+vector(0, fudge, 0),box = False)
ylabel = label(text = "y", color = yaxis.color, pos=yaxis.axis+vector(0, fudge, 0),box = False)
zlabel = label(text = "-z", color = zaxis.color, pos=zaxis.axis+vector(0, fudge, 0),box = False)
# To make axes visible or invisible
axes = [xaxis, negXaxis, yaxis, negYaxis, zaxis, negZaxis, xlabel, ylabel, zlabel]
return
makeAxes(1)
g = shapes.gear(n = 20)
gear1 = extrusion (path = [vector(0, 0, 0), vector(0, 0, 0.1)], shape=g, opacity = 0.4)
# gear1.axis = vector(0, 0, 0)
debugArrow=arrow(length=6,shaftwidth=.1,color=color.white,axis=vector(0,0,0))
gearAxisArrow=arrow(shaftwidth=.1, color=color.red)
inputYawAngleYaxis = 0 # int(input("Enter an angle: "))
while True:
for cir in np.arange(0, 2*np.pi, 0.01):
rate(10)
# sleep(1)
pitch=0
# k = vector(cos(yaw)*cos(pitch), sin(pitch),sin(yaw)*cos(pitch)) ''' with pitch input '''
k = vector(cos(cir), 0 ,sin(cir)) # ''' without pitch input '''
y=vector(0,0,0)
s=cross(k,y)
v=cross(s,k)
rad = radians(45)
# gear1.axis = vector(1.23, -1.77418, 0) #vector(cos(inputYawAngleYaxis * pi/180), sin(pitch),sin(inputYawAngleYaxis* pi/180)*cos(pitch))
# gear1.pos = vector(-2.94957, 0, 2.70185)
# Gear Pos0: <0.707107, 0, 0.707107> Gear Axis0: <2.15647, 0.101243, -0.00237659>
gear1.pos = vector(0.707107, 0, 0.707107)
# gear1.pos = debugArrow.axis #frontArrow.axis # k # vector(0.707107, 0, 0.707107)
gear1.rotate(angle = -0.1, axis = vector(0, 0, 1), origin = vector(0, 0, 1 ))
# gear1.axis = vector(cos(radians(-45)), 0, sin(radians(-45)))
''' DebugArrow represents the position of the gear's center '''
debugArrow.axis = vector(cos(rad), 0, sin(rad))
''' Arrow inside the gear to track rotational axis of gear - This is to debug the yaw issue facing with gear object'''
gearAxisArrow.pos = gear1.pos
gearAxisArrow.axis = gear1.axis # vector(cos(radians(-45)), 0, sin(radians(-45))) # gear1.axis
gearAxisArrow.length = gear1.length/2
## Debugg
# print("Front Arrow Axis: ", frontArrow.axis, " K vec: ", k, " Ball pos: ", ball.pos )
print("Gear Pos0: ", gear1.pos, " Gear Axis0: ", gear1.axis, "gearAxisArrow: ", gearAxisArrow.pos, "gearAxisArrow: ", gearAxisArrow.axis)
'
I don't understand "I want the gear to remain rotating about Z axis but I would like to yaw the gear around Y-axis". If by "yaw" you mean that the axis of the gear should rotate about the y axis (while the gear itself rotates about that rotating axis), then obviously the axis of the gear can't remain in the direction of the z axis. Instead, the axis of the gear has to rotate. If it's of any help, here is the relevant page of the documentation:
https://www.glowscript.org/docs/VPythonDocs/rotation.html

Dynamically created GUI in Roblox

I am coding my first game using lua and roblox studio. I have a couple of questions regarding GUI. I have coded a very rudimentary gui that displays the code of the four teams that can join the game. Here is the code for the GUI. It lives in a local script inside StarterGUI:
local UpdateGUI = game.ReplicatedStorage:WaitForChild("UpdateGUI")
local StartGui = game.ReplicatedStorage:WaitForChild("StartGui")
local UpdateAllScoresLateArrival = game.ReplicatedStorage:WaitForChild("UpdateAllScoresLateArrival")
local function updateAllLabelsLateArrival(redPoints, bluePoints, yellowPoints, greenPoints)
game.Players.LocalPlayer.PlayerGui.ScreenGui.RedTeam.Text = redPoints
game.Players.LocalPlayer.PlayerGui.ScreenGui.BlueTeam.Text = bluePoints
game.Players.LocalPlayer.PlayerGui.ScreenGui.YellowTeam.Text = yellowPoints
game.Players.LocalPlayer.PlayerGui.ScreenGui.GreenTeam.Text = greenPoints
end
local function UpdateLabel(plr, points)
if plr.team.Name == "Really red Team" then
game.Players.LocalPlayer.PlayerGui.ScreenGui.RedTeam.Text = points
elseif plr.team.Name == "Really blue Team" then
game.Players.LocalPlayer.PlayerGui.ScreenGui.BlueTeam.Text = points
elseif plr.team.Name == "New Yeller Team" then
game.Players.LocalPlayer.PlayerGui.ScreenGui.YellowTeam.Text = points
elseif plr.team.Name == "Lime green Team" then
game.Players.LocalPlayer.PlayerGui.ScreenGui.GreenTeam.Text = points
end
end
local localPlayer = game.Players.LocalPlayer
local function StartLabel(player)
if player.Team.Name == "Really red Team" then
game.Players.LocalPlayer.PlayerGui.ScreenGui.RedTeam.TextTransparency = 0
game.Players.LocalPlayer.PlayerGui.ScreenGui.RedTeamTag.TextTransparency = 0
game.Players.LocalPlayer.PlayerGui.ScreenGui.RedTeam.TextStrokeTransparency = 0
game.Players.LocalPlayer.PlayerGui.ScreenGui.RedTeamTag.TextStrokeTransparency = 0
game.Players.LocalPlayer.PlayerGui.ScreenGui.RedTeamTag.BackgroundTransparency = 0.5
elseif player.Team.Name == "Really blue Team" then
game.Players.LocalPlayer.PlayerGui.ScreenGui.BlueTeam.TextTransparency = 0
game.Players.LocalPlayer.PlayerGui.ScreenGui.BlueTeamTag.TextTransparency = 0
game.Players.LocalPlayer.PlayerGui.ScreenGui.BlueTeam.TextStrokeTransparency = 0
game.Players.LocalPlayer.PlayerGui.ScreenGui.BlueTeamTag.TextStrokeTransparency = 0
game.Players.LocalPlayer.PlayerGui.ScreenGui.BlueTeamTag.BackgroundTransparency = 0.5
elseif player.Team.Name == "New Yeller Team" then
game.Players.LocalPlayer.PlayerGui.ScreenGui.YellowTeam.TextTransparency = 0
game.Players.LocalPlayer.PlayerGui.ScreenGui.YellowTeamTag.TextTransparency = 0
game.Players.LocalPlayer.PlayerGui.ScreenGui.YellowTeam.TextStrokeTransparency = 0
game.Players.LocalPlayer.PlayerGui.ScreenGui.YellowTeamTag.TextStrokeTransparency = 0
game.Players.LocalPlayer.PlayerGui.ScreenGui.YellowTeamTag.BackgroundTransparency = 0.5
elseif player.Team.Name == "Lime green Team" then
game.Players.LocalPlayer.PlayerGui.ScreenGui.GreenTeam.TextTransparency = 0
game.Players.LocalPlayer.PlayerGui.ScreenGui.GreenTeamTag.TextTransparency = 0
game.Players.LocalPlayer.PlayerGui.ScreenGui.GreenTeam.TextStrokeTransparency = 0
game.Players.LocalPlayer.PlayerGui.ScreenGui.GreenTeamTag.TextStrokeTransparency = 0
game.Players.LocalPlayer.PlayerGui.ScreenGui.GreenTeamTag.BackgroundTransparency = 0.5
end
end
UpdateGUI.OnClientEvent:Connect(UpdateLabel)
StartGui.OnClientEvent:Connect(StartLabel)
UpdateAllScoresLateArrival.OnClientEvent:Connect(updateAllLabelsLateArrival)
There is a function that starts the label that is triggered in a server side script when a player joins the game. By ''start the label'' I mean that the labels are there with a transparency of 1 and the function makes them visible when a player joins. There is a function that updates the label everytime any player scores, and a function that is triggered also when a player joins the game late to make sure it has the scores of the players already in the game. Like I said this is my first game and I was focusing on things working. Now I would like to code it properly. My goal is that the labels are allocated dynamically. That is, when a player joins the game, the label is created in code. Particularly I would want the space between the labels to be set dynamically so that the labels are centred regardless of how many players. I tried making the labels a child of a ''frame'' but the labels changed place and were difficult to manipulate. So I would like some advice as to how to set this up in code.
My goal is that the labels are allocated dynamically. That is, when a player joins the game, the label is created in code
You can create UI elements the same way you create Instances in the Workspace.
local lblTeam = Instance.new("TextLabel")
lblTeam.TextTransparency = 0
lblTeam.TextStrokeTransparency = 0
lblTeam.Name = teamName
lblTeam.Parent = game.Players.LocalPlayer.PlayerGui.ScreenGui
I would want the space between the labels to be set dynamically so that the labels are centered regardless of how many players there are.
The way UI elements are laid out in Roblox are with UDim2 values for Size and Position.
A UDim2's constructor looks like this : UDim2.new(xScale, xOffset, yScale, yOffset). Scale refers to with percentage of the parent container should this dimension span, and Offset are the number of pixels extra to add. So some examples :
local lbl = Instance.new("TextLabel")
lbl.Size = UDim2.new(0, 50, 0, 10) -- 50 pixel wide and 10 pixel tall
lbl.Size = UDim2.new(1, 0, 1, 0) -- 100% wide by 100% tall
lbl.Size = UDim2.new(1, -10, 1, -10) -- 100% wide and tall, minus 10 pixels on both bottom and right
-- assuming no changes to AnchorPoint...
lbl.Position = UDim2.new(0, 0, 0, 0) -- upper left corner is upper left corner of parent
lbl.Position = UDim2.new(0.5, 0, 0.5, 0) -- upper left corner is dead center
lbl.Position = UDim2.new(1, 0, 0, 0) -- upper left corner is offscreen on the right
Now, if you want your stuff to be dynamically placed, you could manually place these objects using Positions, but I would recommend using a UIListLayout object and using the LayoutIndex property to automatically place objects for you. It will automatically handle the Position property for you.
local function createTeamUI(name, parent, teamName, index)
-- make a small frame to hold each team UI
-- looks like : [[ Team Tag Label ][ Team Points Label ]]
local teamFrm = Instance.new("Frame")
teamFrm.BackgroundTransparency = 1
teamFrm.Size = UDim2.new(1, 0, 0, 30) -- relative to parent : 100% wide, 30px tall
teamFrm.Name = name
teamFrm.LayoutIndex = index
local lblTeamTag = Instance.new("TextLabel", teamFrm)
lblTeamTag.TextTransparency = 0
lblTeamTag.TextStrokeTransparency = 0
lblTeamTag.Name = "TeamTag"
lblTeamTag.Text = teamName
lblTeamTag.Size = UDim2.new(0.5, 0, 1, 0) -- relative to teamFrm : 50% wide, 100% tall
lblTeam.Position = UDim2.new(0, 0, 0, 0)
local lblPoints = Instance.new("TextLabel", teamFrm)
lblPoints.TextStrokeTransparency = 0
lblPoints.BackgroundTransparency = 0.5
lblPoints.Name = "Points"
lblPoints.Text = "0"
lblPoints.Size = UDim2.new(0.5, 0, 1, 0) -- relative to teamFrm
lblPoints.Position = UDim2.new(0.5, 0, 0, 0)
-- optimization : set the parent last
teamFrm.Parent = parent
return teamFrm
end
local function createAllTeamLabels()
-- creates a list of UI
local frm = Instance.new("Frame")
frm.Name = "Teams"
frm.Size = UDim2.new(0.3, 0, 1, 0)
frm.BackgroundTransparency = 1.0
local layout = Instance.new("UIListLayout")
layout.LayoutOrder = Enum.SortOrder.LayoutIndex
layout.FillDirection = Enum.FillDirection.Vertical
layout.Padding = UDim.new(0, 10) -- 10 pixels between each element in the list
local frmTeamA = createTeamLabel("RedTeam", frm, "Really Red Team", 0)
local frmTeamB = createTeamLabel("BlueTeam", frm, "Blue Team", 1)
local frmTeamC = createTeamLabel("GreenTeam", frm, "Green Team", 2)
frm.Parent = game.Players.LocalPlayer.PlayerGui.ScreenGui
end
local function updatePoints(teamName, points)
game.Players.LocalPlayer.PlayerGui.ScreenGui.Teams[teamName].Points.Text = tostring(points)
end
I have noticed that when a player dies, the GUI disappears on respawn
There is a property on ScreenGuis called ResetOnSpawn that you can change to false. That will keep the UI around even after a player resets.
Since you are making your UI dynamically in code, you should be careful that you aren't accidentally creating the UI multiple times. Here's where the differences between StarterPlayer > StarterPlayerScripts and StarterPlayer > StarterCharacterScripts become important. A LocalScript inside StarterPlayerScripts will run when the player first joins, and a LocalScript inside StarterCharacterScripts will run every time the player's character reloads. So be careful where you fire the code to create the UI.
Hope this helps!

love2d connecting line segment objects to make a pencil tool that draws lines

I'm trying to create a game that is similar to line rider. I've kind of programmed a pencil right now except that the lines are scattered objects.
I want to be able to connect those red dots to make a smooth line so that the ball can roll across it.
It should more look like this
This is my code
function love.load()
printx = 0 --position to be drawn on when the mouse is pressed
printy = 0 --position to be drawn on when the mouse is pressed
love.physics.setMeter(64) --the height of a meter our worlds will be 64px
world = love.physics.newWorld(0, 9.81*64, true) --The world the everything exists in. Horizontal gravity=0. Bertical gravity=9.81. True says that the world is allowed to sleep.
objects = {} -- table to hold all our physical objects
--let's create the ground
objects.lines = {}
objects.ground = {}
objects.ground.body = love.physics.newBody(world, 650/2, 650-50/2)
objects.ground.shape = love.physics.newRectangleShape(650, 50) --make a rectangle with a width of 650 and a height of 50
objects.ground.fixture = love.physics.newFixture(objects.ground.body, objects.ground.shape); --attach shape to body
--let's create a ball
objects.ball = {}
objects.ball.body = love.physics.newBody(world, 650/2, 600, "dynamic") --Determines where the object will start. In the center of the world and dynamic(moves around)
objects.ball.shape = love.physics.newCircleShape(20) --the ball's shape has a radius of 20
objects.ball.fixture = love.physics.newFixture(objects.ball.body, objects.ball.shape, 1) -- Attach fixture to body and give it a density of 1.
--initial graphics setup
love.graphics.setBackgroundColor(0.41, 0.53, 0.97) --set the background color to a nice blue
love.window.setMode(650, 650) --set the window dimensions to 650 by 650
end
function love.update(dt)
world:update(dt) --this puts the world into motion
if love.mouse.isDown(1) then
local printx = love.mouse.getX()
local printy = love.mouse.getY()
line = {}
line.body = love.physics.newBody(world, printx, printy, "static")
line.shape = love.physics.newRectangleShape(0, 0, 5, 5)
line.fixture = love.physics.newFixture(line.body, line.shape, 5) -- A higher density gives it more mass.
table.insert(objects.lines, line)
love.graphics.setColor(50,50,50)
love.graphics.polygon("fill", line.body:getWorldPoints(line.shape:getPoints()))
end
end
function love.draw()
love.graphics.setColor(0.28, 0.63, 0.05) -- set the drawing color to green for the ground
love.graphics.polygon("fill", objects.ground.body:getWorldPoints(objects.ground.shape:getPoints())) -- draw a "filled in" polygon using the ground's coordinates
love.graphics.setColor(0.76, 0.18, 0.05) --set the drawing color to red for the ball
love.graphics.circle("fill", objects.ball.body:getX(), objects.ball.body:getY(), objects.ball.shape:getRadius())
for _, block in pairs(objects.lines) do
love.graphics.polygon("fill", block.body:getWorldPoints(block.shape:getPoints()))
end
end
Within love.update
if not love.mouse.isDown(1) then
oldx = nil
oldy = nil
end
--draw lines when the mouse is down
if love.mouse.isDown(1) then
local printx = love.mouse.getX() + Camera.x --x coordinate of the mouse
local printy = love.mouse.getY() + Camera.y --y coordinate of the mouse
if oldx ~= nil then
line = {}
line.x1 = oldx
line.x2 = printx
line.y1 = oldy
line.y2 = printy
line.body = love.physics.newBody(world, 0, 0, "static")
line.shape = love.physics.newEdgeShape(printx, printy, oldx, oldy)
line.fixture = love.physics.newFixture(line.body, line.shape, 5)
table.insert(objects.lines, line)
end
oldx = printx
oldy = printy
end
Within love.draw()
for _, line in pairs(objects.lines) do
love.graphics.line( line.x1 - Camera.x, line.y1 - Camera.y, line.x2 - Camera.x, line.y2 - Camera.y) --:getWorldPoints(block.shape:getPoints()))
end

Bouncing text animation issue in Pygame

I'm trying to code a program that can take text and animate it to bounce on a loop, like a ball bouncing to the floor. I used a similar piece of code I found a starting point as I'm still fairly new to Pygame (thank you Pete Shinners, whoever you are), but after updating the code and playing with it for a long time I still can't get it to blit to the screen correctly. The text starts above the rendered area and then gradually falls into view, but the top part of the text is cut off.
I've tried moving the blitted region around the window and resizing the rectangles and surface the program is using, but nothing seems to fix it.
import os, sys, math, pygame, pygame.font, pygame.image
from pygame.locals import *
def bounce():
# define constants
G = 0.98
FLOOR = 0
COEFFICIENT = 0.8
#define variables
ball = 500
direction = 'DOWN'
v = 0
count = 0
#create array to store data
array = [ball]
while True:
if count == 4:
return array
elif ball > FLOOR and direction == 'DOWN':
v += G
if (ball - v) >= FLOOR:
ball = ball - v
array.append(round(ball,2))
else:
ball = FLOOR
array.append(round(ball,2))
direction = 'UP'
v *= COEFFICIENT
count += 1
elif ball >= FLOOR and direction == 'UP':
v -= G
if (ball + v) >= FLOOR:
ball = ball + v
array.append(round(ball,2))
if v <= 0:
direction = 'DOWN'
else:
ball = FLOOR
array.append(ball)
direction = 'UP'
v *= COEFFICIENT
class textBouncy:
array = bounce()
def __init__(self, font, message, fontcolor, amount=10):
# Render the font message
self.base = font.render(message, 0, fontcolor)
# bounce amount (height)
self.amount = amount
#size = rect of maximum height/width of text
self.size = self.base.get_rect().inflate(0, amount).size
#normalise array to meet height restriction
self.array = [round(-x/(500/amount),2) for x in array]
def animate(self):
# create window surface s
s = pygame.Surface(self.size)
# height = max inflated height
height = self.size[1]
# define a step-sized rectangle in the location of the step
src = Rect(0, 0, self.base.get_width(), height)
# moves the message according to the array list.
dst = src.move(0, self.array[i])
if (i + 1) == len(self.array):
global i
i = 0
# blits the information onto the screen
s.blit(self.base, dst, src)
return s
entry_info = 'Bouncing ball text'
if __name__ == '__main__':
pygame.init()
#create text renderer
i = 0
array = bounce()
bigfont = pygame.font.Font(None, 60)
white = 255, 255, 255
renderer = textBouncy(bigfont, entry_info, white, 16)
text = renderer.animate()
#create a window the correct size
win = pygame.display.set_mode(text.get_size())
win.blit(text, (0, 10))
pygame.display.flip()
#run animation loop
finished = 0
while True:
pygame.time.delay(10)
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
text = renderer.animate()
i += 1
win.blit(text, (0, 10)) # blits the finished product from animate
pygame.display.flip()
(Quote) "it all comes down to math really" Kay so you need to - the y axis when you want to make it go up and + the x axis to make it go side ways you could make it go up and down will moveing it horizontally and then when it reaches a point it will stop moving horizontally and just bonce up and down +ing it more every time
That was my 100$ which took me 5 mins to write
After revisiting this I managed to work this out - I needed to add everything I blitted down to compensate for the bounce up. So in the __init__function:
self.array = [round(-x/(500/amount),2)**+self.amount** for x in array]
Works perfectly now :)

Resources