Blitzmax game suddenly slow
BlitzMax Forums/BlitzMax Beginners Area/Blitzmax game suddenly slow
| ||
So I read the "Blitzmax SLOW SLOW SLOW" thread, and to my surprise discovered I was running a very old Blitzmax. Something like 1.09 or something. "Woah great" I thought, and immediately updated (yes, remembering to uninstall and delete all instances of old blitzmax). PROBLEM! The crappy laptop I use to test my builds on (Windows, celeron 2000ish), to see if they're not too slow, now runs my game at a crawl. It's not even 4 fps. Before, it was smooth even with 4000+ balls on the screen (breakout clone). The other laptop I'm using to code and test on (Pentium M-1.6) runs it just fine. Edit: On yet another machine, it used to run very slow, but it ran. Now it just shows the console window and closes it. (Windows 600mhz) What happened guys? It worked fine with 1.09 and now with 1.16 it's crawling. I'm having the exact opposite problem of the guy in the "Blitzmax SLOW SLOW SLOW" thread.. |
| ||
Maybe the exact opposite is true with your system? Maybe the card is crap with DX (or the DX driver is a problem)? Try using the GL driver again and checking the difference. |
| ||
I've tried both DX and GL, and there's no difference. It's still slow. |
| ||
Can you post some code? |
| ||
Hmm okay, don't see how that could help but alright. Careful or you might go blind from my n00b coding:Strict (whole lot of incbin's removed here, to save space) Graphics 800,600,0 SetClsColor 100,100,100 SetMaskColor 255,255,255'White AutoMidHandle True (more image loading removed) Include "powerup.bmx" Include "particles.bmx" Type obj Field x#, y# Field speed# = 0.1 Field height# Field width# EndType Type tball Extends obj 'note: ball image must be 100x100 pixels Field oldx# = 0, oldy# = 0 Field offsetx# Field dir# = 0 Field radius# = 10 Field oldspeed# = 0 Field sticky = 0 Function newball(radius) Local ball:tball = New tball ball.radius = radius balllist.addlast(ball) EndFunction Method moveball() oldx# = x oldy# = y x#:+ Sin(dir)*speed*time y#:+ Cos(dir)*speed*time EndMethod Method collide() If x <= radius-3 Or x >= 646-radius Then x = oldx ; dir = (180 - dir) + 180 ' left wall and right wall collide check If y <= radius-3 Then y = oldy ; dir = 180 - dir ' top wall and bottom wall collide check Local paddleh# = paddle.height/2 If y+radius >= paddle.y - paddleh ' check if ball is below paddle y Local paddlew# = paddle.width/2 If x+radius > paddle.x-paddlew And x-radius < paddle.x+paddlew Then 'check if ball is between paddle in x If paddle.sticky = 1 If sticky = 0 Then ' set the ball as sticky if it isn't, making it stop etc. sticky = 1 oldspeed = speed speed = 0 offsetx = x-paddle.x If x > paddle.x Then dir = 180 - (x - paddle.x)/2 If x < paddle.x Then dir = 180 + (paddle.x - x)/2 EndIf x = MouseX() + offsetx y = paddle.y - paddleh - radius 'fix the ball height if it's below the paddle If MouseHit(1) Then For Local ball:tball = EachIn balllist 'make sure we release all balls from paddle when mousehit If ball.sticky = 1 Then If ball.speed = 0 Then ball.speed = ball.oldspeed ; ball.oldspeed = 0 ball.sticky = 0 EndIf Next EndIf Else If x > paddle.x Then dir = 180 - (x - paddle.x)/2 If x < paddle.x Then dir = 180 + (paddle.x - x)/2 EndIf Return EndIf EndIf If y >= 600 Then die() EndMethod Method draw() Local ratio# = radius / 100 * 2 SetScale ratio,ratio DrawImage(ballimg, x, y) SetScale 1,1 EndMethod Method die() balllist.remove(Self) EndMethod EndType Type TBrick Extends obj Field strength = 1 Field r,g,b Field powerup = 0 Field number# = 0 Function create(x=200,y=200,h=20,w=70,r=200,g=200,b=255,str=1,powerup=0) Local newbrick:tbrick = New tbrick newbrick.x = x newbrick.y = y newbrick.height = h newbrick.width = w newbrick.r = r newbrick.g = g newbrick.b = b If randompowerups = True Local random = Rand(1,5) If random = 1 Then newbrick.powerup = getrandomeffectnumber() EndIf bricklist.addlast(newbrick) EndFunction Method collide() For Local ball:tball = EachIn balllist Local brickw = width / 2 If ball.x# + ball.radius => x# - brickw Then If ball.x# - ball.radius =< x# + brickw Then Local brickh = height / 2 If ball.y# + ball.radius => y# - brickh Then If ball.y# - ball.radius =< y# + brickh Then If ball.oldy < y - brickh Then ball.dir = 180 - ball.dir ; ball.y = ball.oldy ; die() ; Return If ball.oldy > y + brickh Then ball.dir = 180 - ball.dir ; ball.y = ball.oldy ; die() ; Return If ball.oldx < x - brickw Then ball.dir = 360 - ball.dir ; ball.x = ball.oldx ; die() ; Return If ball.oldx > x + brickw Then ball.dir = 360 - ball.dir ; ball.x = ball.oldx ; die() ; Return EndIf EndIf EndIf EndIf Next EndMethod Method draw() If powerup > 0 Then r = 255 g = 255 b = 10 EndIf SetColor r,g,b DrawImage(brick1img, x, y) Select strength Case 1 DrawImage(cracked_3,x,y) Case 2 DrawImage(cracked_2,x,y) Case 3 DrawImage(cracked_1,x,y) EndSelect EndMethod Method die() If strength = 1 And powerup > 0 Then tpowerup.spawn(x,y,powerup) If strength = 1 Then bricklist.remove(Self) ; 'PlaySound explodesnd ; player1.score:+25 If strength = 1 Then explode(x,y, width/2, height/2,r,g,b) If strength > 1 Then strength:-1 ; 'PlaySound pop ; player1.score:+10 EndMethod EndType Type TPaddle Extends obj Field width# = 190 Field leftwidth# = 15 Field rightwidth# = 15 Field height# = 17 Field x = 0 Field y = 580 Field sticky = 0 Method move() x = MouseX() EndMethod Method draw() Local realwidth = width - leftwidth - rightwidth Local halfwidth = realwidth/2 SetColor 255,255,255 Local MouseX = MouseX() If MouseX < 15 + halfwidth Then MouseX = 15 + halfwidth If MouseX > 630 - halfwidth Then MouseX = 630 - halfwidth MoveMouse MouseX, 550 DrawImage(paddle_leftimg, MouseX-halfwidth-7, 580) SetScale realwidth,1 DrawImage(paddle_middleimg, MouseX, 580) SetScale 1,1 DrawImage(paddle_rightimg, MouseX+halfwidth+8, 580) EndMethod EndType Type player Field lives = 3 Field score = 0 EndType Type background Extends obj Method draw() SetColor 255,255,255 TileImage(tileimg,x,y) x#:+.4*time y#:+.5*time EndMethod EndType Global balllist:TList = CreateList() Global bricklist:TList = CreateList() Global sparklist:TList = CreateList() Global state$ = "menu" Global ball_hold = 1 Global newbackground:background = New background Global player1:player = New player Global time# = 1 Global paddle:tpaddle Repeat If state = "menu" Then menu() If state = "started" Then started() If state = "started" And ListIsEmpty(balllist) Then die() If state = "started" And ListIsEmpty(bricklist) Then die() If state = "gameover" Then gameover() Flip; Cls ' FlushMem -- this did not work with 1.16 Until KeyDown(Key_Escape) Function die() If player1.lives = 0 Then state = "gameover" ; Return player1.lives:-1 tball.newball(10) ball_hold = 1 EndFunction Function gameover() If KeyHit(key_space) state = "menu" ; Return SetBlend(alphablend) newbackground.draw() SetRotation Cos(number)*20 SetScale Cos(number)*1, Cos(Cos(number)*1)*1.2 number:+1 SetColor 0,0,0 SetAlpha 0.1 DrawImage(gameoverimg,400,400) SetColor 255,255,255 SetAlpha 1 DrawImage(gameoverimg,400,300) SetRotation 0 SetColor 0,0,0 SetScale 1,1 DrawText "Press SPACE for menu", 200,550 EndFunction Function menu() SetBlend(alphablend) newbackground.draw() SetAlpha .1 DrawImage(logo_shadowimg, 400, 150) SetAlpha 1 SetColor 255,255,255 DrawImage(logoimg, 400, 100) SetColor 0,0,Rand(100,200) DrawText "Press SPACE to start a new game", 290,300 If KeyHit(key_space) Then newgame() EndFunction Function newgame() tball.newball(10) paddle = New tpaddle player1.lives = 3 player1.score = 0 balllist.clear() bricklist.clear() poweruplist.clear debrislist.clear() Include "level1.bmx" state = "started" EndFunction Function started() newbackground.draw() For Local brick:tbrick = EachIn bricklist brick.collide() brick.draw() Next For Local particle:tparticle = EachIn particlelist particle.move() particle.draw() Next For Local debris:tdebris = EachIn debrislist debris.move() debris.draw() Next For Local ball:tball = EachIn balllist ball.moveball() ball.collide() ball.draw() Next For Local powerup:tpowerup = EachIn poweruplist powerup.move() powerup.collide(paddle.width) powerup.draw() Next paddle.move() paddle.draw() drawstatusbar()'' drawvalues() If ball_hold = 1 ballhold() Else If MouseDown(2) Then matrix() Else time = 1 ; SetAlpha 1 If KeyHit(key_e) Then state = "edit" 'If KeyHit(key_down) Then paddle.width:-50 'If KeyHit(key_up) Then paddle.width:+50 If KeyHit(key_down) Then For Local ball:tball = EachIn balllist ; ball.radius:-30 ; Next If KeyHit(key_up) Then For Local ball:tball = EachIn balllist ; ball.radius:+30 ; Next If KeyHit(key_x) Then For Local brick:tbrick = EachIn bricklist ; brick.die() ; Next If KeyHit(key_4) Then tbrick.create(Rand(40,600), Rand(20,700)) If KeyHit(key_5) Then createballs(5, Rand(4,20)) If KeyHit(key_6) Then Include "level1.bmx" If KeyHit(key_0) Then createballs(100, Rand(1,3)) If KeyHit(key_space) Then For Local ball:tball = EachIn balllist If ball.speed <> 0 ball.speed = 0 Else ball.speed = 5 EndIf Next EndIf EndIf EndFunction Function matrix() DrawText "MATRIX MODE ON",700,580 time = 0.1 EndFunction Function ballhold() For Local ball:tball = EachIn balllist ball.speed = 0 ball.y = MouseY()'550 ball.x = MouseX() Next If MouseHit(1) Then launchball() EndFunction Function launchball() ball_hold = 0 For Local ball:tball = EachIn balllist ball.speed = 6 ball.dir = Rand(135,225) Next EndFunction Function drawstatusbar() SetColor 0,0,0 DrawRect 645,0,5,600 SetColor 201,203,219 DrawRect 650,0,600,800 SetColor 255,255,255 EndFunction Function drawvalues() SetColor 0,0,0 DrawText "Number of balls : "+balllist.Count(), 20, 40 DrawText "Number of bricks : "+bricklist.Count(), 20, 20 DrawText "Score: "+player1.score, 660,100 DrawText "Lives: "+player1.lives, 660,120 EndFunction |
| ||
don't see how that could help You're absolutely right. Without any images (or the chance to sub them for my own) or the include code I have no chance of running this and providing feedback on whether I see the issue on my machines, what their spec is, add debug/timing/memory usage code etc and help you out. So... Why don't you add debug messages to your code so you can determine which function/method is causing the slowdown? |
| ||
Gah, I'm an idiot. Turns out I had to put in SetGraphicsDriver GLMax2DDriver()to actually force it to run in opengl mode. Turns out it runs perfectly now with this mode on my slow test-laptop. |
| ||
"Why don't you add debug messages to your code so you can determine which function/method is causing the slowdown?" Guess you didn't read my initial post. There is no change to the code between the computers, the only change was the difference in BMax versions. Why would I start adding more debug messages when that's not the issue? This was also the reason why I couldn't see a reason to post my code. I omitted the content inclusions because they'll just provide further spam in this thread. |
| ||
How many images and how large images do you load? One reason might be that the drawing has been modified to support more hardware things (T'n'L especially was might not make much of different for regular usage but there are some uses for it). Also the default flags for loading have changed, you might check the BRL.D3D7Max2D implementation to see in the history how that changed and set it for you manually (especially not using filtered images for example) One thing that might help is that you change to manuall GC mode on slow systems like your 600mhz system as automatic GC has an overhead (GCSetMode I think and then GCCollect where you used flushmem before). |
| ||
Most of the images are very small, not over 50x50. Only the logo and game_over logo are bigger, and they're about 400x300 or something. I will never ever code for D3D, because I can't use it on other platforms.. What do you mean by filtered images, and that I must not use them - do you mean images with alpha/transparency? I have no idea what GC mode means or even is, so I will read up on that later when I sit down to code again :) Thanks Dreamora! Here's the images.. Incbin "images\ball.png" Incbin "images\paddle.png" Incbin "images\paddle_left.png" Incbin "images\paddle_right.png" Incbin "images\paddle_middle.png" Incbin "images\tile.png" Incbin "images\brick_1.png" Incbin "images\cracked_1.png" Incbin "images\cracked_2.png" Incbin "images\cracked_3.png" Incbin "images\logo.png" Incbin "images\gameover.png" Incbin "images\logo_shadow.png" Incbin "images\powerup\_tile.png" Incbin "images\powerup\_glass.png" Incbin "images\powerup\faster.png" Incbin "images\powerup\slower.png" Incbin "images\powerup\magnet.png" Incbin "images\powerup\multi3x.png" Incbin "images\powerup\multi5x.png" Incbin "images\powerup\multi9x.png" Incbin "images\powerup\multi15x.png" Incbin "images\powerup\multix2.png" Incbin "images\powerup\multix3.png" Incbin "images\debris\debris001.png" Incbin "images\debris\debris002.png" Incbin "images\debris\debris003.png" Incbin "images\debris\debris004.png" Incbin "images\debris\debris005.png" Incbin "images\debris\debris006.png" Incbin "images\debris\debris007.png" Incbin "images\debris\debris008.png" Incbin "images\debris\debris009.png" Incbin "images\debris\debris010.png" Incbin "images\debris\debris011.png" Incbin "images\debris\debris012.png" Incbin "images\debris\debris013.png" Incbin "images\debris\debris014.png" Incbin "images\debris\debris015.png" Incbin "images\debris\debris016.png" Incbin "images\debris\debris017.png" Global tileimg:Timage=LoadImage("incbin::images\tile.png") Global ballimg:Timage=LoadImage("incbin::images\ball.png") Global paddle_leftimg:Timage=LoadImage("incbin::images\paddle_left.png") Global paddle_middleimg:Timage=LoadImage("incbin::images\paddle_middle.png") Global paddle_rightimg:Timage=LoadImage("incbin::images\paddle_right.png") Global logoimg:Timage=LoadImage("incbin::images\logo.png") Global gameoverimg:Timage=LoadImage("incbin::images\gameover.png") Global logo_shadowimg:Timage=LoadImage("incbin::images\logo_shadow.png") Global brick1img:Timage=LoadImage("incbin::images\brick_1.png") Global cracked_1:Timage=LoadImage("incbin::images\cracked_1.png") Global cracked_2:Timage=LoadImage("incbin::images\cracked_2.png") Global cracked_3:Timage=LoadImage("incbin::images\cracked_3.png") Global tile:Timage=LoadImage("incbin::images\powerup\_tile.png") Global glass:Timage=LoadImage("incbin::images\powerup\_glass.png") Global faster:Timage=LoadImage("incbin::images\powerup\faster.png") Global slower:Timage=LoadImage("incbin::images\powerup\slower.png") Global magnet:Timage=LoadImage("incbin::images\powerup\magnet.png") Global multi3x:Timage=LoadImage("incbin::images\powerup\multi3x.png") Global multi5x:Timage=LoadImage("incbin::images\powerup\multi5x.png") Global multi9x:Timage=LoadImage("incbin::images\powerup\multi9x.png") Global multi15x:Timage=LoadImage("incbin::images\powerup\multi15x.png") Global multix2:Timage=LoadImage("incbin::images\powerup\multix2.png") Global multix3:Timage=LoadImage("incbin::images\powerup\multix3.png") |
| ||
First, what is the status of the problem? Does it run OK in either DX and/or GL mode on Bmax 1.16? Second, adding the debug messages would show if it was a general slowdown or a specific area of code which slowed down. If, for example, some functions were slower than before you coulc the similarity of commands and usen them to review changes in Bmax source code. Third, posting your code allows other people to feedback on whether they see the same problems. If they do then more people are available to diagnose the problem and/or make suggestions and/or give advice. Make sense? |
| ||
Careful or you might go blind from my n00b coding: At least you indent. :o> |
| ||
tonyg, as I said above, it's fixed. I simply run it OpenGL on 1.16, which is what I want to use anyway, since it's multiplatform. Turns out 1.16 defaulted to D3D, and 1.09 defaulted to OpenGL. So that was the problem. If anyone wants, feel free to comment on my code in other areas.. I'd be very happy if you did, it can only be improved from here. I'm a newbie at this, so there's probably a lot of rules and laws I've carelessly stepped on. |
| ||
I would not use that many program scope globals. Instead I would use them in a scoped manner like: Type TEffectImages Global brick1img:Timage=LoadImage("incbin::images\brick_1.png") Global cracked_1:Timage=LoadImage("incbin::images\cracked_1.png") Global cracked_2:Timage=LoadImage("incbin::images\cracked_2.png") Global cracked_3:Timage=LoadImage("incbin::images\cracked_3.png") Global tile:Timage=LoadImage("incbin::images\powerup\_tile.png") Global glass:Timage=LoadImage("incbin::images\powerup\_glass.png") Global faster:Timage=LoadImage("incbin::images\powerup\faster.png") Global slower:Timage=LoadImage("incbin::images\powerup\slower.png") Global magnet:Timage=LoadImage("incbin::images\powerup\magnet.png") Global multi3x:Timage=LoadImage("incbin::images\powerup\multi3x.png") Global multi5x:Timage=LoadImage("incbin::images\powerup\multi5x.png") Global multi9x:Timage=LoadImage("incbin::images\powerup\multi9x.png") Global multi15x:Timage=LoadImage("incbin::images\powerup\multi15x.png") Global multix2:Timage=LoadImage("incbin::images\powerup\multix2.png") Global multix3:Timage=LoadImage("incbin::images\powerup\multix3.png") end type You can access them using TEffectImages.multix3 for example. Might look useless bu perhaps you are later going to implement some effect classes which then can extend TEffectImages and straight accessing them like local images. But there is nothing "eye killing noobish" in your code at all :-) |
| ||
Ahh I see your point, but don't you mean to make them local within the class then? Otherwise it would still work my old way, with adding the effect classes if they were global ; the effects classes would be able to see them anyway, without a class. |
| ||
No local is of no use as then every instance of the class would hold a reference to them. The way above they only exist for all instances of the class and extended classes (-> only 1 reference per image to take care off) Only only thought encapsulate them might help keeping the application "global free" if the images are not really needed to be global at all. But this logically only makes sense if you create effect classes. Otherwises it would be a useless "more work" :-) |
| ||
ouch! some indenting from hell...easy there :p ;) - damned thing nearly had my eye out :] |
| ||
Hi. I'm new to BlitzMax. I was looking over this thread, and ran across Dreamora's advice to couch global image declarations in a Type. I tried to convert the graphics in my current project to that system. It looks like Dreamora's example, but now I get a compile error: "Type global initializers must be constant." Can anyone tell me what the problem is? |
| ||
I will never ever code for D3D, because I can't use it on other platforms.. To be honest, in my experience D3D doesn't even work well amongst the various Windows versions. OpenGL in BMax blows away the D3D performance.Just an FYI, but if you are used to using an older version of BMax, the flush mem stuff has changed too ;c) |
| ||
Psychotronic: You haven't updated to BM 1.16 then. This error comes up if you do Type test global img:TImage = loadimage(...) end type If you insist on staying on the outdated version you must do the following type test global img:timage method new() if img = null then img = loadimage(..) ... end method end type |
| ||
"ouch! some indenting from hell...easy there :p ;)" What's wrong with my indenting? I use 4space, but seems this site decided to make them 10 spaces or so. Other than that, what's wrong? |
| ||
Dreamora: Thank you. I figured since I just downloaded BlitzMax, I would have the most updated version, but I'm all fixed up now. |