Here is my attempt at making an oldschool dot ball, the rotation code I found laying around in an old word document of mine (along with other snippets) so I cannot say with total honesty if I wrote that part or not :O
I mainly wrote this as an exercise of using functions in types which is slowly beginning to sink in at last & is probably far from the best example. Any suggestions of improvements or if/where I have failed would be welcomed
// --------------------------------- //
// Project: dotball
// Start: Tuesday, February 28, 2012
// IDE Version: 10.244
// FREE-VERSION:
// Need Premium for Features:
// 3D Graphics
// Network Commands
// INLINE C/C+++ code
// SETCURRENTDIR("Media") // go to media files
GLOBAL DB AS dotball, scx, scy
GETSCREENSIZE scx, scy
TYPE point
x
y
z
ENDTYPE
TYPE dotball
xrot
yrot
zrot
ballpoints[] AS point
FUNCTION createball: pointcount
LOCAL theta, phi, loop
DIM self.ballpoints[pointcount]
FOREACH loop IN self.ballpoints[]
theta = RND (180)-90
phi = RND (359)
loop.x = (COS(theta) * 10) * (COS(phi) * 10)
loop.y = (COS(theta) * 10) * (SIN(phi) * 10)
loop.z = SIN(theta) * 100
NEXT
ENDFUNCTION
FUNCTION drawball: sx,sy,sz
LOCAL tmpx, tmpy, tmpz, px, loop, persp, x%, y%, colour%
persp = 400
FOREACH loop IN self.ballpoints[]
tmpy = ((loop.y * COS(self.xrot)) - (loop.z * SIN(self.xrot)))
tmpz = ((loop.y * SIN(self.xrot)) + (loop.z * COS(self.xrot)))
tmpx = ((loop.x * COS(self.yrot)) - (tmpz * SIN(self.yrot)))
tmpz = ((loop.x * SIN(self.yrot)) + (tmpz * COS(self.yrot)))
px = tmpx
tmpx = ((tmpx * COS(self.zrot)) - (tmpy * SIN(self.zrot)))
tmpy = ((px * SIN(self.zrot)) + (tmpy * COS(self.zrot)))
x = (512 * (tmpx) / (persp - (tmpz))) + (scx/2)
y = (scy/2) - (512 * tmpy) / (persp - (tmpz))
colour = tmpz + 155
DRAWRECT x,y,2,2,RGB(colour,colour,colour)
NEXT
INC self.xrot , sx
INC self.yrot , sy
INC self.zrot , sz
ENDFUNCTION
ENDTYPE
DB.createball(500)
WHILE TRUE
DB.drawball(1,0.75,0.5)
SHOWSCREEN
WEND
Lee
That's really rather nice :)
Wow simply great.
With various code like this also, I feel an old school sinusoidal intro demo coming on:
http://www.glbasic.com/forum/index.php?topic=7669.0
A simple change I just noticed from looking at the code ( & why I did not do it in the 1st place I have no idea ) is to add an x & y to the function call drawball so you can draw it where you like rather than centred. Have changed the code to do that now but you can leave the last 2 parameters off & it will centre it like before.
Lee
// --------------------------------- //
// Project: dotball
// Start: Tuesday, February 28, 2012
// IDE Version: 10.244
// FREE-VERSION:
// Need Premium for Features:
// 3D Graphics
// Network Commands
// INLINE C/C+++ code
// SETCURRENTDIR("Media") // go to media files
GLOBAL DB AS dotball, scx, scy
GETSCREENSIZE scx, scy
TYPE point
x
y
z
ENDTYPE
TYPE dotball
xrot
yrot
zrot
ballpoints[] AS point
FUNCTION createball: pointcount
LOCAL theta, phi, loop
DIM self.ballpoints[pointcount]
FOREACH loop IN self.ballpoints[]
theta = RND (180)-90
phi = RND (359)
loop.x = (COS(theta) * 10) * (COS(phi) * 10)
loop.y = (COS(theta) * 10) * (SIN(phi) * 10)
loop.z = SIN(theta) * 100
NEXT
ENDFUNCTION
FUNCTION drawball: sx,sy,sz,posx=scx/2,posy=scy/2
LOCAL tmpx, tmpy, tmpz, px, loop, persp, x%, y%, colour%
persp = 400
FOREACH loop IN self.ballpoints[]
tmpy = ((loop.y * COS(self.xrot)) - (loop.z * SIN(self.xrot)))
tmpz = ((loop.y * SIN(self.xrot)) + (loop.z * COS(self.xrot)))
tmpx = ((loop.x * COS(self.yrot)) - (tmpz * SIN(self.yrot)))
tmpz = ((loop.x * SIN(self.yrot)) + (tmpz * COS(self.yrot)))
px = tmpx
tmpx = ((tmpx * COS(self.zrot)) - (tmpy * SIN(self.zrot)))
tmpy = ((px * SIN(self.zrot)) + (tmpy * COS(self.zrot)))
x = (512 * (tmpx) / (persp - (tmpz))) + (posx)
y = (posy) - (512 * tmpy) / (persp - (tmpz))
colour = tmpz + 155
DRAWRECT x,y,2,2,RGB(colour,colour,colour)
NEXT
INC self.xrot , sx
INC self.yrot , sy
INC self.zrot , sz
ENDFUNCTION
ENDTYPE
DB.createball(500)
WHILE TRUE
DB.drawball(1,0.75,0.5,200,200)
SHOWSCREEN
WEND
Ha, I had no idea what this would do until I ran it! Very cool!
Here's a game idea that came to mind while running this:
- You start with an empty 'room'.
- In this room is an invisible object.
- You have a 'gun' that shoots paint dots (like your sphere) towards the invisible object.
- You can rotate the room in all directions to control where you fire your paint dot.
- Eventually the shape of the invisible object will start revealing itself with more paint dots.
- Try to figure out what the invisible object is! (from a list of common object shapes)
- Scored based on how few paint dots you needed to make accurate guess.
- Or you are trying to get out of an invisible maze, shoot strategic paint dots to see where the walls are.
- Or a form of 'Battleship'. Shoot dots to reveal / guess where the ships are. (ships could be simple cubes, rectangles)
But still a very cool demo!
[Edit] Or instead of ONE invisible object, have multiple very simple shaped objects randomly placed in room, and you have to determine which objects are located where (kinda like the Battleship concept).
Updated now so you can specify scale as well as position (both are optional parameters), hopefully fixed the colour scaling code to return ranges from 0-255, also added a dotcube for the fun of it :D
Todo :
- Add more objects like a torus, cylinder etc
- Fix the cube code so that Z falls in the -100 to 100 range same as sphere (only for the colour code mainly)
- Add a destroy function to clear the array
- Breakout the common rotation code into it's own function
- Numerous other little tweaks & fixes =D
Lee
// --------------------------------- //
// Project: dotball
// Start: Tuesday, February 28, 2012
// IDE Version: 10.244
// FREE-VERSION:
// Need Premium for Features:
// 3D Graphics
// Network Commands
// INLINE C/C+++ code
// SETCURRENTDIR("Media") // go to media files
GLOBAL DB AS dotball, DC AS dotcube, scx, scy
GETSCREENSIZE scx, scy
TYPE point
x
y
z
ENDTYPE
TYPE dotball
xrot
yrot
zrot
ballpoints[] AS point
FUNCTION createball: pointcount
LOCAL theta, phi, loop
DIM self.ballpoints[pointcount]
FOREACH loop IN self.ballpoints[]
theta = RND (180)-90
phi = RND (359)
loop.x = (COS(theta) * 10) * (COS(phi) * 10)
loop.y = (COS(theta) * 10) * (SIN(phi) * 10)
loop.z = SIN(theta) * 100
NEXT
ENDFUNCTION
FUNCTION drawball: sx,sy,sz,posx=scx/2,posy=scy/2,scale=1
LOCAL tmpx, tmpy, tmpz, px, loop, persp, x%, y%, colour%
persp = 400
FOREACH loop IN self.ballpoints[]
tmpy = ((loop.y * COS(self.xrot)) - (loop.z * SIN(self.xrot)))
tmpz = ((loop.y * SIN(self.xrot)) + (loop.z * COS(self.xrot)))
tmpx = ((loop.x * COS(self.yrot)) - (tmpz * SIN(self.yrot)))
tmpz = ((loop.x * SIN(self.yrot)) + (tmpz * COS(self.yrot)))
px = tmpx
tmpx = ((tmpx * COS(self.zrot)) - (tmpy * SIN(self.zrot)))
tmpy = ((px * SIN(self.zrot)) + (tmpy * COS(self.zrot)))
x = ((scale*512) * (tmpx) / (persp - (tmpz))) + (posx)
y = (posy) - ((scale*512) * tmpy) / (persp - (tmpz))
colour = (tmpz+100) * 1.2
DRAWRECT x,y,2,2,RGB(colour,colour,colour)
NEXT
INC self.xrot , sx
INC self.yrot , sy
INC self.zrot , sz
ENDFUNCTION
ENDTYPE
TYPE dotcube
xrot
yrot
zrot
cubepoints[] AS point
FUNCTION createcube: pointcount
LOCAL loop, across, down, side
DIM self.cubepoints[pointcount]
FOREACH loop IN self.cubepoints[]
side = RND (5)
across = RND (120)
down = RND (120)
SELECT side
CASE 0 // Front face
loop.x = across-60
loop.y = down-60
loop.z = 60
CASE 1 // Back face
loop.x = across-60
loop.y = down-60
loop.z = -60
CASE 2 // Left face
loop.x = -60
loop.y = down-60
loop.z = across-60
CASE 3 // Right face
loop.x = 60
loop.y = down-60
loop.z = across-60
CASE 4 // Top face
loop.x = across-60
loop.y = 60
loop.z = down-60
CASE 5 // Bottom Face
loop.x = across-60
loop.y = -60
loop.z = down-60
ENDSELECT
NEXT
ENDFUNCTION
FUNCTION drawcube: sx,sy,sz,posx=scx/2,posy=scy/2,scale=1
LOCAL tmpx, tmpy, tmpz, px, loop, persp, x%, y%, colour%
persp = 400
FOREACH loop IN self.cubepoints[]
tmpy = ((loop.y * COS(self.xrot)) - (loop.z * SIN(self.xrot)))
tmpz = ((loop.y * SIN(self.xrot)) + (loop.z * COS(self.xrot)))
tmpx = ((loop.x * COS(self.yrot)) - (tmpz * SIN(self.yrot)))
tmpz = ((loop.x * SIN(self.yrot)) + (tmpz * COS(self.yrot)))
px = tmpx
tmpx = ((tmpx * COS(self.zrot)) - (tmpy * SIN(self.zrot)))
tmpy = ((px * SIN(self.zrot)) + (tmpy * COS(self.zrot)))
x = ((scale*512) * (tmpx) / (persp - (tmpz))) + (posx)
y = (posy) - ((scale*512) * tmpy) / (persp - (tmpz))
colour = (tmpz+100) * 1.2
DRAWRECT x,y,2,2,RGB(colour,colour,colour)
NEXT
INC self.xrot , sx
INC self.yrot , sy
INC self.zrot , sz
ENDFUNCTION
ENDTYPE
DC.createcube(1000)
DB.createball(1000)
WHILE TRUE
DC.drawcube(0.5,0.75,1,250,150,1)
DB.drawball(1,0.75,0.5,400,400,0.5)
SHOWSCREEN
WEND
Thats fun. I flippin love it. =D
Couple of things I thought of. Try drawing the screen with ALPHAMODE 1.0 to see if you like the effect better than the default mode. I wonder if you might also get a performance boost by replacing the DRAWRECT command with a series of POLYVECTOR sprites.
Quote from: matchy on 2012-Feb-29
Wow simply great.
With various code like this also, I feel an old school sinusoidal intro demo coming on:
http://www.glbasic.com/forum/index.php?topic=7669.0
Do it!
Quote from: Wampus on 2012-Feb-29
Thats fun. I flippin love it. =D
Couple of things I thought of. Try drawing the screen with ALPHAMODE 1.0 to see if you like the effect better than the default mode. I wonder if you might also get a performance boost by replacing the DRAWRECT command with a series of POLYVECTOR sprites.
Glad you like it =D
Not to sure about ALPHAMODE mainly because I have not played around with that command yet but will have a go. The DRAWRECT was used as I didn't like the way 1x1 pixels looked & just needed something quick to view the output, also POLYVECTORS are another area I need to play around with as no experience with them as such yet.
Lookup tables for SIN/COS might give a boost, not so much on PC's I think but some of the lower spec targets like WinCE, Cannoo etc might benefit from them.
It was more or less coded in 1 sitting so there are bound to be some further optimisations that can be made as I focused on the effect rather than the performance (as well as learning types a bit more).
Your comments for improvements/ideas are appreciated & welcomed, if anyone else has any please post them =D
Lee
update:
- Rolled the creation of the objects into the same type & made the type an array so you can create multiple objects easy if you need.
- Doing the above has removed duplicate code somewhat
- Added a "killobject" function to freeup memory
// --------------------------------- //
// Project: dotobject
// Start: Wednesday, February 29, 2012
// IDE Version: 10.244
// FREE-VERSION:
// Need Premium for Features:
// 3D Graphics
// Network Commands
// INLINE C/C+++ code
// SETCURRENTDIR("Media") // go to media files
GLOBAL dobj[] AS dotobject, scx, scy, alphaloop, alphastep, ikey$
GETSCREENSIZE scx, scy
TYPE point
x
y
z
ENDTYPE
TYPE dotobject
xrot
yrot
zrot
objectpoints[] AS point
FUNCTION createball: pointcount
LOCAL theta, phi, loop
DIM self.objectpoints[pointcount]
FOREACH loop IN self.objectpoints[]
theta = RND (180)-90
phi = RND (359)
loop.x = (COS(theta) * 10) * (COS(phi) * 10)
loop.y = (COS(theta) * 10) * (SIN(phi) * 10)
loop.z = SIN(theta) * 100
NEXT
ENDFUNCTION
FUNCTION createcube: pointcount
LOCAL loop, across, down, side
DIM self.objectpoints[pointcount]
FOREACH loop IN self.objectpoints[]
side = RND (5)
across = RND (120)
down = RND (120)
SELECT side
CASE 0 // Front face
loop.x = across-60
loop.y = down-60
loop.z = 60
CASE 1 // Back face
loop.x = across-60
loop.y = down-60
loop.z = -60
CASE 2 // Left face
loop.x = -60
loop.y = down-60
loop.z = across-60
CASE 3 // Right face
loop.x = 60
loop.y = down-60
loop.z = across-60
CASE 4 // Top face
loop.x = across-60
loop.y = 60
loop.z = down-60
CASE 5 // Bottom Face
loop.x = across-60
loop.y = -60
loop.z = down-60
ENDSELECT
NEXT
ENDFUNCTION
FUNCTION drawobject: sx,sy,sz,posx=scx/2,posy=scy/2,scale=1
LOCAL tmpx, tmpy, tmpz, px, loop, persp, x%, y%, colour%
persp = 400
FOREACH loop IN self.objectpoints[]
tmpy = ((loop.y * COS(self.xrot)) - (loop.z * SIN(self.xrot)))
tmpz = ((loop.y * SIN(self.xrot)) + (loop.z * COS(self.xrot)))
tmpx = ((loop.x * COS(self.yrot)) - (tmpz * SIN(self.yrot)))
tmpz = ((loop.x * SIN(self.yrot)) + (tmpz * COS(self.yrot)))
px = tmpx
tmpx = ((tmpx * COS(self.zrot)) - (tmpy * SIN(self.zrot)))
tmpy = ((px * SIN(self.zrot)) + (tmpy * COS(self.zrot)))
x = ((scale*512) * (tmpx) / (persp - (tmpz))) + (posx)
y = (posy) - ((scale*512) * tmpy) / (persp - (tmpz))
colour = (tmpz+100) * 1.2
DRAWRECT x,y,2,2,RGB(colour,colour,colour)
NEXT
INC self.xrot , sx
INC self.yrot , sy
INC self.zrot , sz
ENDFUNCTION
FUNCTION killobject:
DIM self.objectpoints[0]
ENDFUNCTION
ENDTYPE
REDIM dobj[2]
dobj[0].createball(1000)
dobj[1].createcube(500)
alphaloop = -1
alphastep = 0.01
WHILE TRUE
ALPHAMODE alphaloop
dobj[0].drawobject(1,0.75,0.5,400,400,.25)
dobj[1].drawobject(0.5,0.75,1,250,150,1)
SHOWSCREEN
ikey$=INKEY$()
IF ikey$ = "0" THEN dobj[0].killobject()
IF ikey$ = "1" THEN dobj[1].killobject()
IF alphaloop > 1.0 THEN alphastep = -0.01
IF alphaloop < -1.0 THEN alphastep = 0.01
INC alphaloop, alphastep
WEND