I've got a CASIO fx-CG50 with python running extended version of micropython 1.9.4
Decided to make a game but I really need a sleep function, I cannot use any imports as everything is pretty barebones. Any help would be greatly appreciated.
I've tried downloading utilities but they're just extra applications, nothing seems to really exist for the casio.
Cheers!
If you cannot import time (or utime) in your code, you could always implement a simple function that loops for a certain number of steps:
def wait(step):
for i in range(step):
pass
wait(999999)
In that case, the actual time spent in the function will depend on the computational power of your device.
I am trying to do the same exact things and I was trying to benchmark a wait function by animating a square accross the scree. Here is what I have come up width:
from casioplot import *
def wait(milli):
time = milli*50
for i in range(time):
pass
def drawSquare(x,y,l):
for i in range(l):
for j in range(l):
set_pixel(x+j,y+i,(0,0,0))
draw_string(0, 0, "start.", (0, 0, 0,), "small")
show_screen()
waitMillis = 1000
screenWidth = 384
screenHeight = 192
xPos = 0
yPos = 0
squareSide = 24
while xPos + squareSide < screenWidth:
clear_screen()
drawSquare(xPos,yPos,squareSide)
show_screen()
wait(waitMillis)
xPos = xPos + 5
draw_string(int(screenWidth/2), 0, "done", (0, 0, 0,), "small")
show_screen()
So when just using a manual stopwatch app, I noticed that the wait function has a 1 second turnaround time for every 50k iterations. So I set a ratio to the value in order
to have a comfortable millisecond parameter. Unfortunately, performance degrade drastically probably do to the drawing utilities and the constant clear and setting of pixels. The performance degradation is exponential and it is hard to capture and control. The square moves well up to half of the screen after which it moves very sluggishly so. I am not sure if we can fix this problem easily...
Related
So, i'm doing little game with python and pyglet, but i'm stuck with moving the object in xy axis.
I have object A which is dictionary, it has x-coordinate, y-coordinate and speedvectors for x and y.
When i launch this object A it flies like it should, the problem is i'm moving it like this.
objectA["y"] = objectA.get("y") + objectA.get("ySpeed")
objectA["x"] = objectA.get("x") + objectA.get("xSpeed")
So the coordinates are moving rapidly like first objextA x is 130 then its 160 etc. When i'm trying to do some collision things, object wont stop because it doesn't register hit, it skips over the block (or atleast i think it does so). Any tips how i should actually do this?
Your code is correct. I tested it in an empty script and it worked fine
Try this in a empty script and look at the results. It should first print 0 and then print 10:
objectA = {"x": 0, "y": 0, "xSpeed": 1, "ySpeed": 1}
print(objectA["x"])
for _ in range(10):
objectA["x"] = objectA.get("x") + objectA.get("xSpeed")
print(objectA["x"])
It might be something else in your code that causes the problem.
Btw, this is a shorter way of writing your posted code (it does exactly the same):
objectA["x"] += objectA["xSpeed"]
objectA["y"] += objectA["ySpeed"]
For my project in AH Computing I'm recreating my version of Nidhogg. Everything runs smoothly until the blood starts spraying. Im not too sure how i can make the code more efficient as i am still fairly new to python.
This is the class for the the spraying blood:
class bloodmaker():
def __init__(self,xv,yv,colour,x,y):
self.gravity = 2
self.air_resistance = 0.25
self.xv = xv
self.yv = yv
self.x = x
self.y = y
self.pastx = 0
self.pasty = 0
self.colour = colour
def move(self):
if self.y < 400:
self.pastx = self.x
self.pasty = self.y
#so that it doesnt curve backwards
if self.xv > 0:
self.xv -= self.air_resistance
self.yv += self.gravity
self.x += self.xv
self.y += self.yv
#so that the drawn line doesnt go over the edge
if self.y > 400:
self.y = 400
if self.colour is "o":
py.draw.line(screen, (255, 165, 0), (self.pastx-backgroundx, self.pasty), (self.x-backgroundx, self.y),5)
else:
py.draw.line(screen, (255, 255, 0), (self.pastx-backgroundx, self.pasty), (self.x-backgroundx, self.y),5)
else:
global bloodgrid
try:
#the bloodgrid are squares 5 pixels wide, covering the bottom section, so we we divide by 5 to find where to put the blood
bloodgrid[int(self.x/5)].insert(0,self.colour)
except:
pass
#deleting this object as it is no longer required
return True
[Here is an image of the blood spraying][1]
(excuse the incomplete sprite)
[1]: https://i.stack.imgur.com/hXiAa.png
Underneath there is a floor of blood that works using an array of stacks, which is added above code when it the blood reaches the floor.
bloodgrid = [[] for x in range(512)]
Here is the code for destroying the flying blood object and blitzing the blood floor to the screen.
def blood():
for i in range(len(bloodarray)):
killyourself = bloodarray[i].move()
if killyourself is True:
kill.append(i)
#appends to a kill list as if i popped here the list would get shorter while the for loop stays the same giving an out of index error
for i in range(len(kill)):
bloodarray.pop(kill[0]-i)
kill.pop(0)
#printing the entire bloodgrid
for i in range(512):
for ii in range(len(bloodgrid[i])):
try:
if bloodgrid[i][ii] is "o":
py.draw.rect(screen, (255, 165, 0), ((i*5)-backgroundx, ii*5+400, 5, 5))
else:
py.draw.rect(screen, (255, 255, 0), ((i*5)-backgroundx, ii*5+400, 5, 5))
except:
pass
I don't think it is possible to only update parts of the screen as the camera moves about and the blood on the floor moves too.
As more blood accumulates on the floor the game framerate starts to drop and it gets especially choppy when the blood sprays. Is there any ways I could make this more efficient? I don't want to hand in a choppy game but I really like how the blood looks. Thanks.
A couple of points that are hopefully helpful.
(This isn't directly related to speeding up your code, but...) Try to get away from using global variables. Just pass them into your functions. Several of the ones you posted are difficult to figure out because you are accessing variables that are outside the scope of the function.
First reason things are bogging down here: You are using insert() to insert new elements at the start of a list, and you are doing that inside of a loop where you call the move() function. Inserting anywhere into a list (except the end) is horribly slow for reasons beyond the scope of this post. You should consider putting a deque from collections in there, which can be inserted front or back efficiently. If that is daunting, you could also "do a little math" and insert at the end of your list and draw it backwards by counting down from the last element, which is also efficient.
Also in the same notion, as mentioned in the comments, poping things out of the middle of lists or arrays is also horribly slow. Figure out a different way or look at a different data structure. It is tough to give advice on this point because bloodarray is not defined in your code.
Basically: things are bogging down because you are choosing the wrong data structures. tweak a couple of them and you'll get better results.
The Problem:
Given 3 inputs Bounce, Ball drop height, and ball view height.
How do I calculate the number of times the observer can see the ball pass.
So my code gives correct output, but it takes a longer time as bounce approaches 1, how do I make it deterministic in nature.
def bouncingBall(h, bounce, window):
BounceFactor = bounce
BallDropHeight = h
ViewerHeight = window
BounceLeft = h
BallSeenTimes = 1
if bounce > 1 or bounce < 0 or window >= h or h ==0:
return -1
else:
while (BounceLeft > ViewerHeight):
BounceLeft = BounceLeft * BounceFactor
if (BounceLeft > ViewerHeight):
BallSeenTimes = BallSeenTimes + 2
else:
break
return BallSeenTimes
I am not looking for code answers, just the direction in which I need to think.
Currently, I think If I could somehow establish a linear relationship and create a function to "guess" the passes it would be faster.
Not sure how much this is right. But,
var heightDiff = (BallDropHeight - ViewerHeight);
var reducedHeight = BallDropHeight *(1 - BounceFactor);
var BallSeenTimes = ((heightDiff/reducedLength)*2)+1;
may actually solve it. You just need to find the height reduced on each bounce. Then dividing the height difference between viewer and ball drop point with the reducedHeight will give the number of times ball bounced above the viewer. After that, multiplying with 2 is for each bounce viewer will see it twice. And adding one is for the first time drop.
There is no loop involved in it. So, the time taken to execute will be small only. Hopefully, it helps.!
Background Information - I'm attempting to create somewhat of animation for a frame object with TKinter with the following code:
from tkinter import Frame, Tk, Label, Button
import time
def runAnim():
for width in range(0, 200):
app.after(5000, lambda width = width: test_label.config(width=width))
app = Tk()
app.geometry("500x500")
test_label = Frame(bg="#222", width=0)
test_label.pack(side="left", fill="y")
test_button = Button(text="toggle", command=lambda: runAnim() )
test_button.pack(side="right")
The problem is that it this is not producing the desired behaviour. My understanding is that this should gradually increase the width every 5 seconds, however the 0-200 range seems to complete within these 5 seconds, rather than it being an increased width of 1 every 5 seconds.
Any solutions would be appreciated!
That after(5000, …) means 5 seconds after right now, as after is being called, not 5 seconds after some future point in time that tkinter can only guess by reading your mind.
So, you're just creating 200 callbacks, and scheduling them all to run 5 seconds from now. That's obviously not what you want, but it's what you're asking for, so that's what you get.
In general, you can't do loops like this in event-based programming. What you need to do is turn the loop inside-out: each step does one iteration, then schedules the next call for the next one.
The fully-general transformation looks like this:
def runAnim():
iterwidth = iter(range(0, 200))
stepAnim(iterwidth)
def stepAnim(iterwidth):
try:
width = next(iterwidth)
except StopIteration:
return
test_label.config(width=width))
app.after(5000, stepAnim, iterwidth)
While that works for any iterable, when you're just iterating over numbers, it's usually a bit nicer to turn the for loop into an explicit counter, which is easier to invert. (Yes, that's the opposite of the "usual for instead of while and += 1 when you're not inverting things. The difference is that here, we can't access the magic of for or while, and while is a lot less magical, and therefore easier to invert.)
def runAnim():
stepAnim(0, 200):
def stepAnim(width, maxWidth):
test_label.config(width=width))
width += 1
if width < maxWidth:
app.after(5000, stepAnim, width, maxWidth)
However, in this particularly simple case, you might be able to get away with scheduling 200 callbacks, ranging from 5 to 1000 seconds into the future:
def runAnim():
for width in range(0, 200):
app.after(5000 * width, lambda width = width: test_label.config(width=width))
This might cause the timer to drift a lot more badly, or it might even choke up the scheduler and add lag to your program, but it's at least worth trying.
Speaking of drift:
Back at the start, I mentioned that after(5000, …) means 5 seconds after right now.
An after can fire a bit late. As the docs say: "Tkinter only guarantees that the callback will not be called earlier than that; if the system is busy, the actual delay may be much longer."
So, what happens if it fires after, say, 5.2 seconds? Then the second tick happens 5 seconds after that, at 10.2 seconds, not at 10 seconds. And if they're all firing a bit late, that adds up, so by the end, we could be 20 seconds behind.
Worse, what if after fires exactly at 5.0 seconds, but the Label.config takes 0.2 seconds to run? Then we're absolutely guaranteed to be 20 seconds behind. (Plus any additional error from after itself.)
If this matters, you need to keep track of the desired "next time", and wait until then, not until 5 seconds from whenever it is now. For example:
import datetime as dt
def runAnim():
stepAnim(0, 200, dt.datetime.now() + dt.timedelta(seconds=5):
def stepAnim(width, maxWidth, nextTick):
test_label.config(width=width))
width += 1
if width < maxWidth:
now = dt.datetime.now()
delay = (nextTick - now).total_seconds() * 1000
nextTick += dt.timedelta(seconds=5)
app.after(delay, stepAnim, width, maxWidth, nextTick)
I'm working on a galactica type of game using pygame and livewires. However, in this game, instead of enemy's, there are balloons that you fire at. Every 25 mouse clicks, I have the balloons move down a row using the dy property set to a value of 1. If a balloon reaches the bottom, the game is over. However, I'm having some trouble figuring out how to get this to run only for, say, 1 second, or 2 seconds. Because I don't have a way to "time" the results, the dy value just indefinitely gets set to 1. Therefore, after the first 25 clicks, the row just keeps moving down. This is ok, but like I said, it's not my intended result.
Here is the code I have so far for this action:
if games.mouse.is_pressed(0):
new_missile = missile(self.left + 6, self.top)
games.screen.add(new_missile)
MISSILE_WAIT = 0 #25
CLICKS += 1
if CLICKS == 25:
SPEED = 1
CLICKS = 0
CLICKS, and MISSILE_WAIT are global variables that are created and set to an initial value of 0 before this block of code. What I'm trying to figure out is the algorithim to put underneath the if CLICKS statement. I've looked through the python documentation on the time module, but just can't seem to find anything that would suit this purpose. Also, I don't think using a while loop would work here, because the computer checks those results instantly, while I need an actual timer.
I'm not sure if I got your question but what I can suggest is that:
class Foo():
def __init__(self):
self.start_time = time.time()
self.time_delay = 25 # seconds
def my_balloon_func(self):
if(time.time() - self.start_time) > self.time_delay:
self.start_time = time.time()
else:
# do something