I was just mucking about this evening trying stuff out on my oldest machine mostly to work out whether I could do realtime deforming of a terrain ( like the worms games ) and I ended up with this test code showing how not to do it ( using 1 huge image ) and how it could be done ( using tiled images ). Move the mouse around while pressing left mouse button to erase parts of the image.
Constants define the size of the tiles and how big a block to erase so I could try various combo's.
Is this something anyone else might find useful ?.. I was just gonna shove it up in the code archives but I thought Id see whether its actually worthy.. or whether it would be a waste of space.
Constants define the size of the tiles and how big a block to erase so I could try various combo's.
Is this something anyone else might find useful ?.. I was just gonna shove it up in the code archives but I thought Id see whether its actually worthy.. or whether it would be a waste of space.
SuperStrict ' ' Example of how to perform realtime deformable terrains ' This program performs 2 tests. ' In each test a background image is drawn. An eraser moves around under the mouse. ' while holding down the left mouse button the program will erase the section of the background under the eraser. ' Test 1 ' Using 1 huge image for the background. This method is how NOT to do it. ' ' For test 2 ( press Escape to move on to test 2 ) ' Using Tiles for the background ' ' With the default settings my old Mac (400Mhz PowerPC G4 ) I get the following. ' test 1: ' Not erasing : 222 fps ' Erasing : 3 fps ' test 2: ' No Erasing : 217 fps ' Erasing : 75-80 fps Graphics 640,480 Local image:TImage Const ERASERSIZE:Int = 50 Const TILESIZE:Int = 64 ' This first test is where the background image is one huge image ' This turns out to be very slow. No Suprises there image = CreateImage(640,480,1,DYNAMICIMAGE) resetImage(image,0) While Not KeyHit(KEY_Escape) Local xPos:Int Local ypos:Int Cls DrawImage(image,0,0) xPos = MouseX() - (ERASERSIZE/2) yPos = MouseY() - (ERASERSIZE/2) DrawRect(xPos,yPos,ERASERSIZE,ERASERSIZE) If MouseDown(1) Then Local pixmap:TPixmap Local x:Int Local y:Int ' we must lock the image and get the pixmap pixmap = LockImage(image,0) ' for each pixel the erase is above For x = xPos Until xPos + ERASERSIZE For y = yPos Until yPos + ERASERSIZE ' if the pixel is within the image If x >= 0 And x < 640 And y >= 0 And y < 480 Then ' we can clear out the pixel WritePixel(pixmap,x,y,$ff000000) End If Next Next ' dont forget to unlock the image UnlockImage(image,0) End If DrawText ("FPS:"+(Int(CountFPS())),0,0) Flip 0 Wend ' This second test is where the background image is made up of tiles ' This turns out to be much faster. Fast enough for realtime terrain deformation ? image = CreateImage(TILESIZE,TILESIZE,(640/TILESIZE)*(480/TILESIZE),DYNAMICIMAGE) Local frame:Int For frame = 0 Until (640/TILESIZE)*(480/TILESIZE) resetImage(image,frame) Next While Not KeyHit(KEY_Escape) Local xPos:Int Local ypos:Int Local x:Int Local y:Int Cls For y = 0 Until 480/TILESIZE For x = 0 Until 640/TILESIZE DrawImage(image,x*TILESIZE,y*TILESIZE,y*(640/TILESIZE)+x) Next Next xPos = MouseX() - (ERASERSIZE/2) yPos = MouseY() - (ERASERSIZE/2) DrawRect(xPos,yPos,ERASERSIZE,ERASERSIZE) If MouseDown(1) Then Local pixmap:TPixmap Local minTileX:Int Local maxTileX:Int Local minTileY:Int Local maxTileY:Int Local tileX:Int Local tileY:Int Local tileXPos:Int Local tileYPos:Int ' First the leftmost and rightmost tiles that the eraser covers minTileX = xPos / TILESIZE maxTileX = (xPos+ERASERSIZE)/TILESIZE ' find the top and bottom tiles that the eraser covers minTileY = yPos / TILESIZE maxTileY = (yPos+ERASERSIZE)/TILESIZE ' make sure we dont end up trying to refernce a tile that does not exist maxTileX = Min(maxTileX,(640/TILESIZE)-1) maxTileY = Min(maxTileY,(480/TILESIZE)-1) minTileX = Max(minTileX,0) minTileY = Max(minTileY,0) ' for each tile the eraser is over For tileY = minTileY To maxTileY For tileX = minTileX To maxTileX ' we must lock the image and get the pixmap pixmap = LockImage(image,tileY*(640/TILESIZE)+tileX) ' loop over each y position of the eraser on the screen For y = yPos Until yPos + ERASERSIZE ' calculate the y position within the tile tileYPos = y - tileY * TILESIZE ' if the y position in the tile is actually inside the tile If tileYPos >= 0 And tileYPos < TILESIZE Then ' loop over each x position of the eraser on the screen For x = xPos Until xPos + ERASERSIZE ' calculate the x position within the tile tileXPos = x - tileX * TILESIZE ' if the x position in the tile is actually inside the tile If tileXPos >= 0 And tileXPos < TILESIZE Then ' we can clear out the pixel WritePixel(pixmap,tileXPos,tileYPos,$ff000000) End If Next End If Next ' dont forget to unlock the image. UnlockImage(image,0) Next Next End If DrawText ("FPS:"+(Int(CountFPS())),0,0) Flip 0 Wend Global fps:Float, fpst:Float,fpsc:Float Function resetImage(image:TImage, frame:Int) Local pixmap:TPixmap Local r:Int Local g:Int Local b:Int r = Rand(128,255) g = Rand(128,255) b = Rand(128,255) pixmap = LockImage(image,frame) ClearPixels(pixmap,$ff Shl 24 | r Shl 16 | g Shl 8 | b) UnlockImage(image) End Function Function CountFPS:Float() If fpst < MilliSecs() Then fpst=MilliSecs()+1000 fps = fpsc fpsc = 0 Else fpsc = fpsc + 1 End If Return fps End Function