AI TANKS first draft
Re: AI TANKS first draft
Hi basiccoder2.
for a continuous loop you have to overlap the ends of the fixed points.
pts(Ubound(pts))=pts(4)
pts(Ubound(pts)-1)=pts(3)
pts(Ubound(pts)-2)=pts(2)
pts(Ubound(pts)-3)=pts(1)
where the lbound is 1 here.
The spline goes through each point EXACTLY.
So a simple goto starts over.
If cout(n).x=pts(Ubound(pts)-2).x And n<> Lbound(cout) Then Goto start
The angle between spline points is simply
For n As Long=Lbound(cout) To Ubound(cout)-1
...
Var a=Atan2(-(cout(n+1).y-cout(n).y),(cout(n+1).x-cout(n).x))'slope of curve
(a is the angle)
then swing the image by this angle, or try angle +pi/2 if it needs adjusted.
for a continuous loop you have to overlap the ends of the fixed points.
pts(Ubound(pts))=pts(4)
pts(Ubound(pts)-1)=pts(3)
pts(Ubound(pts)-2)=pts(2)
pts(Ubound(pts)-3)=pts(1)
where the lbound is 1 here.
The spline goes through each point EXACTLY.
So a simple goto starts over.
If cout(n).x=pts(Ubound(pts)-2).x And n<> Lbound(cout) Then Goto start
The angle between spline points is simply
For n As Long=Lbound(cout) To Ubound(cout)-1
...
Var a=Atan2(-(cout(n+1).y-cout(n).y),(cout(n+1).x-cout(n).x))'slope of curve
(a is the angle)
then swing the image by this angle, or try angle +pi/2 if it needs adjusted.
-
- Posts: 3906
- Joined: Jan 01, 2009 7:03
- Location: Australia
Re: AI TANKS first draft
In all my other code it rotates clockwise so I need the same for all rotation routines so there is no conflict.badidea wrote:BasicCoder2 wrote:The problem is that the screen coordinates are upside down. Then when we do positive rotation, should we go clockwise or counter-clock?
Code: Select all
Const Pi = 4 * Atn(1)
Dim Shared As single TwoPi = 8 * Atn(1)
Dim Shared As single RtoD = 180 / Pi ' radians * RtoD = degrees
Dim Shared As single DtoR = Pi / 180 ' degrees * DtoR = radians
screenres 640,480,32
dim as single cx,cy,dx,dy,rad
cx = 320
cy = 240
rad = 100
for angle as single = 0 to 359 step 45
dx = cos(angle*DtoR)*rad
dy = sin(angle*DtoR)*rad
line (cx,cy)-(cx+dx,cy+dy)
pset(cx+dx,cy+dy)
draw string (cx+dx,cy+dy),str(angle)
next angle
sleep
Re: AI TANKS first draft
So frustrating... I was looking into my old tank game from 2012. I still have a working executable with sound, but unable so far to compile it again.
Had to disable all the old fbsound stuff. On FBC 64-bit immediate crash. Not so strange, because I assumed integers 32 bit back then.
But with FBC 32-bit it starts loading stuff, but then freezes. Somewhere at map loading or displaying it goes wrong, but I do not understand my old code.
My idea was to get it running, do some code clean up, use the new fbsound version. But still stuck at step 1.
Had to disable all the old fbsound stuff. On FBC 64-bit immediate crash. Not so strange, because I assumed integers 32 bit back then.
But with FBC 32-bit it starts loading stuff, but then freezes. Somewhere at map loading or displaying it goes wrong, but I do not understand my old code.
My idea was to get it running, do some code clean up, use the new fbsound version. But still stuck at step 1.
-
- Posts: 3906
- Joined: Jan 01, 2009 7:03
- Location: Australia
Re: AI TANKS first draft
@badidea,
I assume it was this game?
http://nr100.home.xs4all.nl/badidea/tank_game_01.png
Perhaps start again using the skills you must have acquired over the past six years?
Only this time write it a way that is easy to modify and that you (and maybe others) can read years later :)
I assume it was this game?
http://nr100.home.xs4all.nl/badidea/tank_game_01.png
Perhaps start again using the skills you must have acquired over the past six years?
Only this time write it a way that is easy to modify and that you (and maybe others) can read years later :)
Re: AI TANKS first draft
Yes that game, but there was already a lot of work in it. Sound, explosion animations, collisions, a map editor, even had a buggy network version for up to 8 clients. Worked on windows and linux.BasicCoder2 wrote:@badidea,
I assume it was this game?
http://nr100.home.xs4all.nl/badidea/tank_game_01.png
Perhaps start again using the skills you must have acquired over the past six years?
Only this time write it a way that is easy to modify and that you (and maybe others) can read years later :)
I prefer code clean-up over restart, because writing something similar twice isn't fun. There are a lot of shared variables and code distributed over different files in a not so logic way. Big puzzle.
I saw that I was changing something to the map routines in 2012 because there are tab-indents there where most code uses space indents.
I'll continue investigation tomorrow...
Sometimes you also loose knowledge over time. I did quite some assembly routines in PowerBasic a long time ago for fast graphics. I would probably need to learn that over again. Not that I would want that. Graphics is fast enough these days (mostly due to the hardware), and if not, go with opengl or something.
-
- Posts: 3906
- Joined: Jan 01, 2009 7:03
- Location: Australia
Re: AI TANKS first draft
@badidea,
How was your investigations? I see it started the project back in 2010.
https://nr100.home.xs4all.nl/badidea/ta ... al_05.html
Writing it as a tutorial was potentially a good idea as it forces you to think clearly about what you are doing and may be helpful to others as well. It seems to me you need to start on building the basic structure of a particular type of game, in this case a tile based 2d game, after which you add things in an essentially modular fashion. Even if you did start again, this time writing the code with future modifications and readability in mind, you can still use all those resources you mention such as sound, animations, map editor and so on. Even when I do a rewrite, as I am doing now, I copy paste sections of previous code. The more modular the code the easier it is to do. I have found a rewrite is much faster than the first attempts just because you have a clearer idea as to what needs to be done and how to do it.
How was your investigations? I see it started the project back in 2010.
https://nr100.home.xs4all.nl/badidea/ta ... al_05.html
Writing it as a tutorial was potentially a good idea as it forces you to think clearly about what you are doing and may be helpful to others as well. It seems to me you need to start on building the basic structure of a particular type of game, in this case a tile based 2d game, after which you add things in an essentially modular fashion. Even if you did start again, this time writing the code with future modifications and readability in mind, you can still use all those resources you mention such as sound, animations, map editor and so on. Even when I do a rewrite, as I am doing now, I copy paste sections of previous code. The more modular the code the easier it is to do. I have found a rewrite is much faster than the first attempts just because you have a clearer idea as to what needs to be done and how to do it.
Re: AI TANKS first draft
Got it working in 32-bit:BasicCoder2 wrote:@badidea,
How was your investigations? I see it started the project back in 2010.
Apparently, I was in the middle changing the map into 3 layers when I stopped development.
Still crashes badly with 64-bit fbc.
Errors getting even more cryptic:*** Error in `./tank_game_stand_alone': malloc(): corrupted unsorted chunks 2: 0x00000000014322e0 ***
It seems to crash on my sprite_rotate function :-)tank_game_stand_alone: malloc.c:2394: sysmalloc: Assertion `(old_top == initial_top (av) && old_size == 0) || ((unsigned long) (old_size) >= MINSIZE && prev_inuse (old_top) && ((unsigned long) old_end & (pagesize - 1)) == 0)' failed.
Getting closer, now freezes on the menu screen:
Somewhere in this code there is a bug, can you spot it?
Code: Select all
sub draw_world_tiles()
dim as integer x, y, xi, yi, i
dim as integer xSprite, ySprite
dim as int2d tileIndex, tileOffset
dim as integer iSprMap(MAX_SPR_LAYERS-1)
dim as integer drawMethod(MAX_SPR_LAYERS-1) = {SPRITE_DRAW_PSET, SPRITE_DRAW_TRANS, SPRITE_DRAW_TRANS}
'get tile index at top-left of the screen
tileIndex.x = scrPosMap.x \ MAP_SPR_XSIZE
tileIndex.y = scrPosMap.y \ MAP_SPR_YSIZE
'and the remainder
tileOffset.x = scrPosMap.x mod MAP_SPR_XSIZE
tileOffset.y = scrPosMap.y mod MAP_SPR_YSIZE
for xi = -1 to (scr.size.x \ MAP_SPR_XSIZE)
xSprite = tileIndex.x + xi
x = xi * MAP_SPR_XSIZE - tileOffset.x
for yi = -1 to (scr.size.y \ MAP_SPR_YSIZE) + 1
ySprite = tileIndex.y + yi
y = yi * MAP_SPR_YSIZE - tileOffset.y
'check if within boundaries of the map
if (map.validSpritePos(xSprite, ySprite) = 0) then
for i = 0 to MAX_SPR_LAYERS-1
iSprMap(i) = map.getSpriteId(xSprite, ySprite, i)
if (iSprMap(i) <> 0) then 'skip sprite 0
spriteLayer(i).pSprites[iSprMap(i)].drawxym(x, y, drawMethod(i))
else
if (i = 0) then line(x,y)-step(31,31), &h000000, bf 'unless layer 0
end if
next
else
line(x,y)-step(31,31), &h404040, bf 'outside array
end if
next
next
end sub
64-bit ok now.
map.getSpriteId(..) was using an integer ptr, now long ptr
Enough for today.
-
- Posts: 3906
- Joined: Jan 01, 2009 7:03
- Location: Australia
Re: AI TANKS first draft
I noticed in the Seek and Destroy game it is the world that rotates not the main tank (or helecopter).
In most scrolling games the main character is kept center (if possible) but rotates while the world scrolls up/down or left/right.
So which type of display are you going to use?
I experimented with the rotating world display as shown in the link (image) below.
The car is from the racing car demo.
It grabs an area around the position of the car in the main bitmap and then rotates that area rather than the car so that the car is always pointing upwards in the display as in the Seek & Destroy display.
In most scrolling games the main character is kept center (if possible) but rotates while the world scrolls up/down or left/right.
So which type of display are you going to use?
I experimented with the rotating world display as shown in the link (image) below.
The car is from the racing car demo.
It grabs an area around the position of the car in the main bitmap and then rotates that area rather than the car so that the car is always pointing upwards in the display as in the Seek & Destroy display.
-
- Posts: 3906
- Joined: Jan 01, 2009 7:03
- Location: Australia
Re: AI TANKS first draft
Decided to convert images to data statements and post the code although it needs tweaking.
Code: Select all
'dodicat regulator
Function Regulate(Byval MyFps As Long,Byref fps As Long) As Long
Static As Double timervalue,lastsleeptime,t3,frames
Var t=Timer
frames+=1
If (t-t3)>=1 Then t3=t:fps=frames:frames=0
Var sleeptime=lastsleeptime+((1/myfps)-T+timervalue)*1000
If sleeptime<1 Then sleeptime=1
lastsleeptime=sleeptime
timervalue=T
Return sleeptime
End Function
'badidea's sprite rotate
sub sprite_rotate(srcImg as any ptr, dstImg as any ptr, rotation as single, defaultColour as integer)
'replace point & pset with direct memory access
dim as integer srcWidth, srcHeight, srcPitch, dstPitch
dim as single xctr, yctr
dim as integer xdst, ydst
dim as integer xsrc, ysrc
dim as ulong colour 'was integer
dim as single ySin, yCos
dim as single sinRot = sin(rotation)
dim as single cosRot = cos(rotation)
dim as ulong ptr scrPixels, dstPixels 'was integer
imageInfo srcImg, srcWidth, srcHeight, , srcPitch, scrPixels
imageInfo dstImg, , , , dstPitch, dstPixels
dstPitch shr= 2
srcPitch shr= 2
xctr = srcWidth / 2
yctr = srcHeight / 2
for ydst = 0 to srcHeight-1
ySin = (yctr - ydst) * sinRot + xctr + 0.5
yCos = (ydst - yctr) * cosRot + yctr + 0.5
for xdst = 0 to srcWidth-1
xsrc = int((xdst - xctr) * cosRot + ySin)
ysrc = int((xdst - xctr) * sinRot + yCos)
if (xsrc >= 0) and (xsrc < srcWidth) and (ysrc >= 0) and (ysrc < srcHeight) then
'colour = point(xsrc, ysrc, srcImg)
colour = scrPixels[ysrc * srcPitch + xsrc]
else
colour = defaultColour
end if
'pset dstImg, (xdst, ydst), colour
dstPixels[ydst * dstPitch + xdst] = colour
next
next
end sub
const Pi = 4 * Atn(1)
Dim Shared As single TwoPi = 8 * Atn(1)
Dim Shared As single RtoD = 180 / Pi ' radians * RtoD = degrees
Dim Shared As single DtoR = Pi / 180 ' degrees * DtoR = radians
dim shared as long fps 'for dodicat's regulator
'======== SET SCREEN SIZE, INK AND PAPER COLOR ====================
const SCRW = 1280
const SCRH = 480
screenres SCRW,SCRH,32
color rgb(0,0,0),rgb(155,255,155):cls
print "PLEASE WAIT WHILE WORLD FILLS WITH SQUARES"
dim shared as any ptr dest2
dest2 = imagecreate(20,20)
dim shared as any ptr car
car = imagecreate(41,59)
'bload "car.bmp",car
dim as ulong colors( 5)
dim as integer n
colors( 0)=RGB(255,0,255)
colors( 1)=RGB(0,0,0)
colors( 2)=RGB(255,201,14)
colors( 3)=RGB(237,28,36)
colors( 4)=RGB(127,127,127)
for j as integer = 0 to 58
for i as integer = 0 to 40
read n
pset car,(i,j),colors(n)
next i
next j
dim shared as any ptr sCar
sCar = imagecreate(20,20)
'bload "sCar.bmp",sCar
colors( 0)=RGB(255,0,255)
colors( 1)=RGB(0,0,0)
colors( 2)=RGB(127,127,127)
colors( 3)=RGB(237,28,36)
colors( 4)=RGB(255,201,14)
for j as integer = 0 to 19
for i as integer = 0 to 19
read n
pset sCar,(i,j),colors(n)
next i
next j
dim shared as single WINX,WINY,WINW,WINH,WINV,WINA,WORLDW,WORLDH
WORLDW = 2280
WORLDH = 2280
WINX = 100
WINY = 100
WINW = 456
WINH = 456
WINV = 5.0 'velocity
WINA = 0 'angle
dim shared as any ptr world
world = imagecreate(WORLDW,WORLDH,rgb(200,50,0))
dim as integer x,y,r
dim as ulong c
for i as integer = 0 to 1000
x = int(rnd(1)*2280)
y = int(rnd(1)*2280)
r = int(rnd(1)*50)+20
c = rgb( int(rnd(1)*256), int(Rnd(1)*256), int(rnd(1)*256) )
'circle world,(x,y),r,c,,,,f
line world,(x,y)-(x+r,y+r),c,bf
next i
dim shared as any ptr sWorld
sWorld = imagecreate(228,228)
dim as ulong v
for j as integer = 0 to WORLDH-1
for i as integer = 0 to WORLDW-1
v = point(i,j,world)
pset sWorld,(i/10,j/10),v
next i
next j
'bload "sWorld.bmp",sWorld
dim shared as any ptr image
image = imagecreate(WINW,WINH) 'holds grab from world
'destination of rotated images
dim shared as any ptr dest
dest = imagecreate(WINW,WINH) 'hold rotated image
sub display()
screenlock
cls
'get section of world
put image,(0,0),world,(WINX,WINY)-(WINX+WINW,WINY+WINH),trans
sprite_rotate(image,dest,(WINA-270)*DtoR,rgb(255,0,255))
put (20,20),dest,(68,68)-(320+68,320+68),trans
'insert car
put (170-20,170-30),car,trans
put (500,20),sWorld,trans
sprite_rotate(sCar,dest2,(360-WINA)*DtoR,rgb(255,0,255))
put (WINX/10+515,WINY/10+30),dest2,trans
locate 2,2
print "USE ARROW KEYS"
screenunlock
end sub
sub userInput()
'dim as single dx,dy,dd,angle
if multikey(&H50) then WINV = 0 'stop
if multikey(&H48) then WINV = 5 'go
'change direction
if multikey(&H4B) then
WINA = WINA - 2
if WINA < 0 then
WINA = WINA + 360
end if
end if
if multikey(&H4D) then
WINA = WINA + 2
if WINA > 360 then
WINA = WINA - 360
end if
end if
end sub
sub update()
dim as single dx,dy
'move window
dx = cos(WINA*DtoR)*WINV
dy = sin(WINA*DtoR)*WINV
WINX = WINX + dx
WINY = WINY + dy
if WINX < 0 or WINX > WORLDW-WINW or WINY < 0 or WINY > WORLDH - WINH then
WINX = WINX - dx 'undo move
WINY = WINY - dy
end if
line (500,20)-(500+WORLDW\10,20+WORLDH\10),rgb(0,0,0),b
line (500+WINX\10,10+WINY\10)-(500+(WINX+WINW)\10,20+(WINY+WINH)\10),rgb(255,0,0),b
end sub
do
display()
userInput()
update()
sleep regulate(60,fps) '<--------------- set fps here
loop until multikey(&H01)
DATA 0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,1,2,1,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0
DATA 0,0,0,0,0,0,1,3,3,3,3,3,3,3,3,1,1,1,1,2,2,2,1,1,1,1,3,3,3,3,3,3,3,3,1,0,0,0,0,0,0
DATA 0,0,0,0,0,0,1,3,3,3,3,3,3,3,3,3,3,1,2,2,2,2,2,1,3,3,3,3,3,3,3,3,3,3,1,0,0,0,0,0,0
DATA 0,0,0,0,0,0,1,3,3,3,3,3,3,3,3,3,3,1,2,2,2,2,2,1,3,3,3,3,3,3,3,3,3,3,1,0,0,0,0,0,0
DATA 0,0,0,0,0,0,1,3,3,3,3,3,3,3,3,3,3,1,2,2,2,2,2,1,3,3,3,3,3,3,3,3,3,3,1,0,0,0,0,0,0
DATA 0,0,0,0,0,0,1,3,3,3,3,3,1,1,1,1,1,1,2,1,1,1,2,1,1,1,1,1,1,3,3,3,3,3,1,0,0,0,0,0,0
DATA 0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,1,1,3,3,3,1,1,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0
DATA 0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,3,3,3,3,3,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0
DATA 0,1,4,4,4,4,4,4,1,0,0,0,0,0,0,0,0,1,3,3,3,3,3,1,0,0,0,0,0,0,0,0,1,4,4,4,4,4,4,1,0
DATA 0,1,4,4,4,4,4,4,1,0,0,0,0,0,0,0,0,1,3,3,3,3,3,1,0,0,0,0,0,0,0,0,1,4,4,4,4,4,4,1,0
DATA 0,1,4,4,4,4,4,4,1,0,0,0,0,0,0,0,0,1,3,3,3,3,3,1,0,0,0,0,0,0,0,0,1,4,4,4,4,4,4,1,0
DATA 0,1,4,4,4,4,4,4,1,1,1,1,1,1,1,1,1,1,3,3,3,3,3,1,1,1,1,1,1,1,1,1,1,4,4,4,4,4,4,1,0
DATA 0,1,4,4,4,4,4,4,1,1,1,1,1,1,1,1,1,1,3,3,3,3,3,1,1,1,1,1,1,1,1,1,1,4,4,4,4,4,4,1,0
DATA 0,1,4,4,4,4,4,4,1,1,0,0,0,0,0,0,0,1,3,3,3,3,3,1,0,0,0,0,0,0,0,1,1,4,4,4,4,4,4,1,0
DATA 0,1,4,4,4,4,4,4,1,0,1,1,0,0,0,0,0,1,3,3,3,3,3,1,0,0,0,0,0,1,1,0,1,4,4,4,4,4,4,1,0
DATA 0,1,4,4,4,4,4,4,1,0,0,0,1,1,1,0,1,1,3,3,3,3,3,1,1,0,1,1,1,0,0,0,1,4,4,4,4,4,4,1,0
DATA 0,1,4,4,4,4,4,4,1,0,0,0,0,1,1,1,1,1,3,3,3,3,3,1,1,1,1,1,0,0,0,0,1,4,4,4,4,4,4,1,0
DATA 0,0,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,3,3,3,3,3,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,0,0
DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,3,1,1,1,1,1,3,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0
DATA 0,0,0,0,0,0,0,1,1,1,1,1,1,2,2,1,1,1,1,1,4,1,1,1,1,1,2,2,1,1,1,1,1,1,0,0,0,0,0,0,0
DATA 0,0,0,0,0,0,1,2,2,2,2,2,2,2,2,1,1,1,1,4,4,4,1,1,1,1,2,2,2,2,2,2,2,2,1,0,0,0,0,0,0
DATA 0,0,0,0,0,1,2,2,2,2,2,2,2,2,2,1,3,1,1,1,1,1,1,1,3,1,2,2,2,2,2,2,2,2,2,1,0,0,0,0,0
DATA 0,0,0,0,0,1,2,2,2,2,2,2,2,2,2,1,3,1,1,4,1,4,1,1,3,1,2,2,2,2,2,2,2,2,2,1,0,0,0,0,0
DATA 0,0,0,0,0,1,2,2,2,2,2,2,2,2,1,3,3,1,1,4,1,4,1,1,3,3,1,2,2,2,2,2,2,2,2,1,0,0,0,0,0
DATA 0,0,0,0,0,1,2,2,2,2,2,2,2,2,1,3,1,1,1,4,1,4,1,1,1,3,1,2,2,2,2,2,2,2,2,1,0,0,0,0,0
DATA 0,0,0,0,0,1,2,2,2,2,2,2,2,2,1,3,1,1,1,4,1,4,1,1,1,3,1,2,2,2,2,2,2,2,2,1,0,0,0,0,0
DATA 0,0,0,0,0,1,2,2,2,2,2,2,2,2,1,3,1,1,4,1,4,1,4,1,1,3,1,2,2,2,2,2,2,2,2,1,0,0,0,0,0
DATA 0,0,0,0,0,1,2,2,2,2,2,2,2,2,1,3,1,1,1,4,4,4,1,1,1,3,1,2,2,2,2,2,2,2,2,1,0,0,0,0,0
DATA 0,0,0,0,0,1,2,2,2,2,2,2,2,2,1,3,1,1,4,4,4,4,4,1,1,3,1,2,2,2,2,2,2,2,2,1,0,0,0,0,0
DATA 0,0,0,0,0,1,2,2,2,2,2,2,2,2,1,3,3,1,1,1,1,1,1,1,3,3,1,2,2,2,2,2,2,2,2,1,0,0,0,0,0
DATA 0,0,0,0,0,1,2,2,2,2,2,2,2,2,1,3,3,3,1,1,1,1,1,3,3,3,1,2,2,2,2,2,2,2,2,1,0,0,0,0,0
DATA 0,0,0,0,0,1,2,2,2,2,2,2,2,2,1,3,3,3,3,3,3,3,3,3,3,3,1,2,2,2,2,2,2,2,2,1,0,0,0,0,0
DATA 0,0,0,0,0,1,2,2,2,2,2,2,2,2,1,3,3,3,3,1,1,1,3,3,3,3,1,2,2,2,2,2,2,2,2,1,0,0,0,0,0
DATA 0,0,0,0,0,0,1,2,2,2,2,2,2,2,2,1,3,3,3,3,1,3,3,3,3,1,2,2,2,2,2,2,2,2,1,0,0,0,0,0,0
DATA 0,0,0,0,0,0,1,2,2,2,2,2,2,2,2,1,3,3,3,3,1,3,3,3,3,1,2,2,2,2,2,2,2,2,1,0,0,0,0,0,0
DATA 0,0,0,0,0,1,1,2,2,2,2,2,2,2,2,1,3,3,3,3,3,3,3,3,3,1,2,2,2,2,2,2,2,2,1,1,0,0,0,0,0
DATA 0,0,0,0,1,3,1,2,2,2,2,2,2,2,2,1,3,3,3,1,1,1,3,3,3,1,2,2,2,2,2,2,2,2,1,3,1,0,0,0,0
DATA 0,0,0,0,1,3,3,1,2,2,2,2,2,2,2,1,3,3,3,1,4,1,3,3,3,1,2,2,2,2,2,2,2,1,3,3,1,0,0,0,0
DATA 0,0,0,1,3,3,3,1,2,2,2,2,2,2,2,1,3,3,3,1,4,1,3,3,3,1,2,2,2,2,2,2,2,1,3,3,3,1,0,0,0
DATA 0,0,0,1,3,3,3,1,2,2,2,2,2,2,2,1,3,3,3,1,1,1,3,3,3,1,2,2,2,2,2,2,2,1,3,3,3,1,0,0,0
DATA 0,0,0,1,3,3,3,3,1,2,2,2,2,2,2,1,3,3,3,3,1,3,3,3,3,1,2,2,2,2,2,2,1,3,3,3,3,1,0,0,0
DATA 0,0,0,1,3,3,3,3,1,2,2,2,2,2,2,2,1,3,3,3,3,3,3,3,1,2,2,2,2,2,2,2,1,3,3,3,3,1,0,0,0
DATA 0,0,0,1,1,1,1,1,1,1,2,2,2,2,2,2,1,3,3,3,3,3,3,3,1,2,2,2,2,2,2,1,1,1,1,1,1,1,0,0,0
DATA 0,0,0,0,0,0,0,0,0,0,1,2,2,2,2,2,1,3,3,3,3,3,3,3,1,2,2,2,2,2,1,0,0,0,0,0,0,0,0,0,0
DATA 0,0,1,1,1,1,1,1,0,0,0,1,2,2,2,2,2,1,3,3,3,3,3,1,2,2,2,2,2,1,0,0,0,1,1,1,1,1,1,0,0
DATA 0,1,4,4,4,4,4,4,1,0,0,0,1,2,2,2,2,2,1,3,3,3,1,2,2,2,2,2,1,0,0,0,1,4,4,4,4,4,4,1,0
DATA 0,1,4,4,4,4,4,4,1,0,0,0,0,1,1,2,2,2,1,3,3,3,1,2,2,2,1,1,0,0,0,0,1,4,4,4,4,4,4,1,0
DATA 0,1,4,4,4,4,4,4,1,0,0,1,1,0,0,1,2,2,1,3,3,3,1,2,2,1,0,0,1,1,0,0,1,4,4,4,4,4,4,1,0
DATA 0,1,4,4,4,4,4,4,1,1,1,1,1,1,1,1,1,2,1,3,3,3,1,2,1,1,1,1,1,1,1,1,1,4,4,4,4,4,4,1,0
DATA 0,1,4,4,4,4,4,4,1,1,1,1,1,1,1,1,1,2,2,1,3,1,2,2,1,1,1,1,1,1,1,1,1,4,4,4,4,4,4,1,0
DATA 0,1,4,4,4,4,4,4,1,1,1,1,1,1,1,1,1,1,2,1,3,1,2,1,1,1,1,1,1,1,1,1,1,4,4,4,4,4,4,1,0
DATA 0,1,4,4,4,4,4,4,1,0,0,0,0,0,0,0,0,1,2,1,3,1,2,1,0,0,0,0,0,0,0,0,1,4,4,4,4,4,4,1,0
DATA 0,1,4,4,4,4,4,4,1,0,0,0,0,0,0,0,0,1,1,1,3,1,1,1,0,0,0,0,0,0,0,0,1,4,4,4,4,4,4,1,0
DATA 0,1,4,4,4,4,4,4,1,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,1,4,4,4,4,4,4,1,0
DATA 0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0
DATA 0,0,0,0,0,0,0,0,0,0,0,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,0,0,0,0,0,0,0,0,0,0,0
DATA 0,0,0,0,0,0,0,0,0,0,0,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,0,0,0,0,0,0,0,0,0,0,0
DATA 0,0,0,0,0,0,0,0,0,0,0,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,0,0,0,0,0,0,0,0,0,0,0
DATA 0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0
DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
DATA 0,0,0,0,1,1,0,0,0,0,0,0,1,1,1,0,0,0,0,0
DATA 0,0,0,0,2,2,1,3,3,1,1,0,2,2,2,0,0,0,0,0
DATA 0,0,0,0,0,1,0,4,4,4,4,4,0,1,0,3,1,0,0,0
DATA 0,0,0,4,0,1,4,4,4,4,4,4,1,1,0,3,1,0,0,0
DATA 0,0,0,4,1,4,1,3,3,1,1,1,1,1,1,1,0,0,0,0
DATA 0,0,0,4,1,3,3,3,1,2,2,2,3,3,3,4,1,0,0,0
DATA 0,0,0,4,1,4,1,3,3,1,1,1,1,1,1,1,0,0,0,0
DATA 0,0,0,4,0,1,4,4,4,4,4,4,1,1,0,3,1,0,0,0
DATA 0,0,0,0,0,1,0,4,4,4,4,4,0,1,0,3,1,0,0,0
DATA 0,0,0,0,2,2,1,3,3,1,1,0,2,2,2,0,0,0,0,0
DATA 0,0,0,0,1,1,0,0,0,0,0,0,1,1,1,0,0,0,0,0
DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
Re: AI TANKS first draft
Looks cool. The point(..) function seems extreme slow however.
-
- Posts: 3906
- Joined: Jan 01, 2009 7:03
- Location: Australia
Re: AI TANKS first draft
Somewhere I have a faster routine to make a thumbnail image of a much larger image however in this example it only does it once at the start.badidea wrote:Looks cool. The point(..) function seems extreme slow however.
The important part was having a window follow the user controlled object (in the example below shown as a red arrow) and displaying it as always pointing upward while the world moved and rotated around it as I noticed in the Seek and Destroy games on utube.
Last edited by BasicCoder2 on Oct 04, 2018 22:18, edited 1 time in total.
Re: AI TANKS first draft
Yes, I understood that part. How is the performance for a full window view?BasicCoder2 wrote:The important part was having a window follow the user controlled object (in the example below shown as a red arrow) and displaying it as always pointing upward while the world moved and rotated around it as I noticed in the Seek and Destroy games on utube
You can use pointers like in the image_rotate (and drop point() and pset()) for faster world setup.
Sorry, that last one won't work. I understand now that you scale up by ten. But it can be a lot faster because point() is applied to each source pixel 100 times.
Some other remarks:
* TwoPi, RtoD, DtoR can be constants as well. Unless you plan to change them later.
* You do drawing in the update() function, outside the screenlock/unlock.
-
- Posts: 3906
- Joined: Jan 01, 2009 7:03
- Location: Australia
Re: AI TANKS first draft
@badidea,
Latest version on rotating world around the agent which I hope you don't mind is the tank image from https://nr100.home.xs4all.nl/badidea/
Latest version on rotating world around the agent which I hope you don't mind is the tank image from https://nr100.home.xs4all.nl/badidea/
Code: Select all
'dodicat regulator
Function Regulate(Byval MyFps As Long,Byref fps As Long) As Long
Static As Double timervalue,lastsleeptime,t3,frames
Var t=Timer
frames+=1
If (t-t3)>=1 Then t3=t:fps=frames:frames=0
Var sleeptime=lastsleeptime+((1/myfps)-T+timervalue)*1000
If sleeptime<1 Then sleeptime=1
lastsleeptime=sleeptime
timervalue=T
Return sleeptime
End Function
'badidea's sprite rotate
sub sprite_rotate(srcImg as any ptr, dstImg as any ptr, rotation as single, defaultColour as integer)
'replace point & pset with direct memory access
dim as integer srcWidth, srcHeight, srcPitch, dstPitch
dim as single xctr, yctr
dim as integer xdst, ydst
dim as integer xsrc, ysrc
dim as ulong colour 'was integer
dim as single ySin, yCos
dim as single sinRot = sin(rotation)
dim as single cosRot = cos(rotation)
dim as ulong ptr scrPixels, dstPixels 'was integer
imageInfo srcImg, srcWidth, srcHeight, , srcPitch, scrPixels
imageInfo dstImg, , , , dstPitch, dstPixels
dstPitch shr= 2
srcPitch shr= 2
xctr = srcWidth / 2
yctr = srcHeight / 2
for ydst = 0 to srcHeight-1
ySin = (yctr - ydst) * sinRot + xctr + 0.5
yCos = (ydst - yctr) * cosRot + yctr + 0.5
for xdst = 0 to srcWidth-1
xsrc = int((xdst - xctr) * cosRot + ySin)
ysrc = int((xdst - xctr) * sinRot + yCos)
if (xsrc >= 0) and (xsrc < srcWidth) and (ysrc >= 0) and (ysrc < srcHeight) then
'colour = point(xsrc, ysrc, srcImg)
colour = scrPixels[ysrc * srcPitch + xsrc]
else
colour = defaultColour
end if
'pset dstImg, (xdst, ydst), colour
dstPixels[ydst * dstPitch + xdst] = colour
next
next
end sub
const Pi = 4 * Atn(1)
Dim Shared As single TwoPi = 8 * Atn(1)
Dim Shared As single RtoD = 180 / Pi ' radians * RtoD = degrees
Dim Shared As single DtoR = Pi / 180 ' degrees * DtoR = radians
dim shared as long fps 'for dodicat's regulator
const TILEW = 32
const TILEH = 32
const TMAPW = 70
const TMAPH = 70
dim shared as single WINX,WINY,WINW,WINH,WORLDW,WORLDH
WORLDW = TILEW*TMAPW
WORLDH = TILEH*TMAPH
WINX = 100 'position of window within world.bmp with tank in center
WINY = 100
WINW = 456 'size of window to rotate around tank position
WINH = 456
type TANK
as single x
as single y
as single w
as single h
as single v
as single angle
end type
dim shared as TANK t1
'initialize t1
t1.x = 100
t1.y = 100
t1.w = 35
t1.h = 35
t1.v = 0
t1.angle = 0
'======== SET SCREEN SIZE, INK AND PAPER COLOR ====================
const SCRW = 1280
const SCRH = 480
screenres SCRW,SCRH,32
color rgb(0,0,0),rgb(155,255,155):cls
'tank image to overlay on display
dim shared as any ptr tank
tank = imagecreate(35,35)
dim as ulong colors( 7)
colors(0)=RGB(255,0,255)
colors(1)=RGB(0,0,0)
colors(2)=RGB(0,64,0)
colors(3)=RGB(64,128,0)
colors(4)=RGB(128,224,64)
colors(5)=RGB(224,160,0)
colors(6)=RGB(32,96,0)
dim as integer n
for j as integer = 0 to 34
for i as integer = 0 to 34
read n
pset tank,(i,j),colors(n)
next i
next j
t1.v = 5.0 'velocity
t1.angle = 0 'angle direction of tank
dim shared as any ptr world
world = imagecreate(WORLDW,WORLDH,rgb(216,145,89))
dim shared as any ptr thumbnail 'small version of world
thumbnail = imagecreate(224,224,rgb(216,145,89))
'fill with grid
for j as integer = 0 to WORLDH-1 step 32
for i as integer = 0 to WORLDW-1 step 32
line world,(i,j)-(i+32,j+32),rgb(108,70,45),b
next i
next j
dim shared as integer tileMap(0 to 69,0 to 69)
dim as string datum, char
dim as ulong cc
for j as integer = 0 to 69
read datum
for i as integer = 0 to 69
char = mid(datum,i+1,1)
if char = "#" then
cc = rgb( int(rnd(1)*256), int(Rnd(1)*256), int(rnd(1)*256) )
tileMap(i,j)=1
circle world,(i*32-16,j*32-16),13,cc,,,,f
circle thumbnail,((i*32)\10-2,(j*32)\10-2),2,cc,,,,f
end if
next i
next j
'border to make room for rotation near border
for i as integer = 0 to 14
line world,(WINW/2-i,WINH/2-i)-(WORLDW-1-WINW/2+i,WORLDH-1-WINH/2+i),rgb(0,0,0),b
next i
dim shared as any ptr image
image = imagecreate(WINW,WINH) 'image holds grab from world
dim shared as any ptr dest
dest = imagecreate(WINW,WINH) 'dest holds rotated image to display
sub display()
screenlock
cls
'get section of world
put image,(0,0),world,(WINX,WINY)-(WINX+WINW,WINY+WINH),trans
'rotate that section
sprite_rotate(image,dest,(t1.angle-270)*DtoR,rgb(255,0,255))
'display rotated section
put (20,20),dest,(68,68)-(320+68,320+68),trans
'overlay tank image onto display
put (160+20-18,160+20-18),tank,trans
'draw reduced world map
put (500,10),thumbnail,trans
'draw position of tank on reduced world map
line (500+WINX\10+22-2,10+WINY\10+22-2)-(500+WINX\10+22+2,10+WINY\10+22+2),rgb(255,255,0),bf
line (522,31)-(702,211),rgb(0,0,0),b
line (500,9)-(725,234),rgb(0,0,0),b
locate 2,2
print "USE ARROW KEYS",WORLDW,WORLDH
screenunlock
end sub
sub userInput()
'dim as single dx,dy,dd,angle
if multikey(&H50) then t1.v = 0 'stop
if multikey(&H48) then t1.v = 5 'go
'change direction
if multikey(&H4B) then
t1.angle = t1.angle - 2
if t1.angle < 0 then
t1.angle = t1.angle + 360
end if
end if
if multikey(&H4D) then
t1.angle = t1.angle + 2
if t1.angle > 360 then
t1.angle = t1.angle - 360
end if
end if
end sub
sub update()
dim as single dx,dy
'move window
dx = cos(t1.angle*DtoR)*t1.v
dy = sin(t1.angle*DtoR)*t1.v
WINX = WINX + dx
WINY = WINY + dy
if WINX < 50 or WINX > WORLDW-WINW-50 or WINY < 50 or WINY > WORLDH - WINH - 50 then
WINX = WINX - dx 'undo move
WINY = WINY - dy
end if
end sub
do
display()
userInput()
update()
sleep regulate(60,fps) '<--------------- set fps here
loop until multikey(&H01)
DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,4,4,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
DATA 0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,1,3,4,4,1,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0
DATA 0,0,0,0,0,0,1,5,5,5,1,1,0,0,0,0,1,3,1,0,0,0,0,1,1,5,5,5,1,0,0,0,0,0,0
DATA 0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0
DATA 0,0,0,0,0,0,1,5,5,5,1,1,6,6,6,6,1,3,1,6,6,6,6,1,1,5,5,5,1,0,0,0,0,0,0
DATA 0,0,0,0,0,0,1,5,5,5,1,3,3,3,3,3,1,3,1,3,3,3,3,3,1,5,5,5,1,0,0,0,0,0,0
DATA 0,0,0,0,0,0,1,1,1,1,1,4,4,4,4,3,1,3,1,4,4,4,4,4,1,1,1,1,1,0,0,0,0,0,0
DATA 0,0,0,0,0,0,1,5,5,5,1,4,4,4,4,3,1,3,1,4,4,4,4,4,1,5,5,5,1,0,0,0,0,0,0
DATA 0,0,0,0,0,0,1,5,5,5,1,4,4,4,6,1,3,4,4,1,4,4,4,4,1,5,5,5,1,0,0,0,0,0,0
DATA 0,0,0,0,0,0,1,1,1,1,1,4,4,3,6,1,3,4,4,1,4,4,4,4,1,1,1,1,1,0,0,0,0,0,0
DATA 0,0,0,0,0,0,1,5,5,5,1,4,6,1,1,1,1,1,1,1,1,1,4,4,1,5,5,5,1,0,0,0,0,0,0
DATA 0,0,0,0,0,0,1,5,5,5,1,6,1,3,4,4,4,4,4,4,4,4,1,4,1,5,5,5,1,0,0,0,0,0,0
DATA 0,0,0,0,0,0,1,1,1,1,1,6,1,3,4,4,4,4,4,4,4,4,1,4,1,1,1,1,1,0,0,0,0,0,0
DATA 0,0,0,0,0,0,1,5,5,5,1,1,3,4,4,4,4,1,1,1,1,4,4,1,1,5,5,5,1,0,0,0,0,0,0
DATA 0,0,0,0,0,0,1,5,5,5,1,1,3,4,4,4,4,4,4,3,1,4,4,1,1,5,5,5,1,0,0,0,0,0,0
DATA 0,0,0,0,0,0,1,1,1,1,1,1,3,4,4,4,4,4,4,3,1,4,4,1,1,1,1,1,1,0,0,0,0,0,0
DATA 0,0,0,0,0,0,1,5,5,5,1,1,3,4,4,4,3,1,4,3,1,4,4,1,1,5,5,5,1,0,0,0,0,0,0
DATA 0,0,0,0,0,0,1,5,5,5,1,1,3,4,4,4,3,1,1,1,1,4,4,1,1,5,5,5,1,0,0,0,0,0,0
DATA 0,0,0,0,0,0,1,1,1,1,1,1,3,3,4,4,4,4,4,4,4,4,4,1,1,1,1,1,1,0,0,0,0,0,0
DATA 0,0,0,0,0,0,1,5,5,5,1,6,1,3,4,4,4,4,4,4,4,4,1,4,1,5,5,5,1,0,0,0,0,0,0
DATA 0,0,0,0,0,0,1,5,5,5,1,6,1,3,3,4,4,4,4,4,4,4,1,4,1,5,5,5,1,0,0,0,0,0,0
DATA 0,0,0,0,0,0,1,1,1,1,1,4,6,1,1,3,4,4,4,4,1,1,4,4,1,1,1,1,1,0,0,0,0,0,0
DATA 0,0,0,0,0,0,1,5,5,5,1,4,4,6,6,1,1,1,1,1,4,4,4,4,1,5,5,5,1,0,0,0,0,0,0
DATA 0,0,0,0,0,0,1,5,5,5,1,3,3,3,3,3,3,3,3,3,3,3,3,3,1,5,5,5,1,0,0,0,0,0,0
DATA 0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0
DATA 0,0,0,0,0,0,1,5,5,5,1,1,1,1,1,6,6,6,6,6,1,1,1,1,1,5,5,5,1,0,0,0,0,0,0
DATA 0,0,0,0,0,0,1,5,5,5,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,5,5,5,1,0,0,0,0,0,0
DATA 0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0
DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
'tile map
DATA "...........................#.........................................."
DATA "......................................................................"
DATA "......................................................................"
DATA ".........................#.................#....#....................."
DATA "...................................#.....#............................"
DATA ".........................#............................................"
DATA "...................................................................#.."
DATA ".................................................................#...."
DATA "......................................................#..............."
DATA ".....................................................#.....#.........."
DATA ".............#........................................................"
DATA "......................................................................"
DATA "......................................#............................#.."
DATA "......................................................................"
DATA ".................#...................................................."
DATA "......................................................................"
DATA "..................................................#..................."
DATA "............................................#................#........"
DATA "..............................................................#......."
DATA ".............................#...........#............#....#.........."
DATA "......................................................................"
DATA "...................................................#.................."
DATA "..........................#..#........................................"
DATA ".......................#.............................................."
DATA "...................#.......................##........................."
DATA "........................#............................................."
DATA "............................................#.........#..............."
DATA "......................................................................"
DATA "..............#.....................................#................."
DATA "........#.................................#........................#.."
DATA "...................................#.................................."
DATA "..................................#..................................."
DATA "..#..............................................#...................."
DATA "......................#..............................#.....#.........."
DATA ".#...................................................................."
DATA ".......................................................#........#....."
DATA ".................................#...................................."
DATA "......................................................................"
DATA "............#.................#......................................."
DATA ".................................#...................................."
DATA ".#........................................#..........................."
DATA "..................................................#....#.............."
DATA "..............................................#......................."
DATA "......................................................................"
DATA ".......................#...............#.............................."
DATA "............................................#................#........"
DATA "....#................................#.....................#.........."
DATA "....................#................#................................"
DATA "..............................................................#......."
DATA ".............#........................................................"
DATA "...............#......................................................"
DATA "#....................................................................."
DATA ".................................................................#...."
DATA ".....................................#.................#.............."
DATA "......................................................................"
DATA ".......................#.............................................."
DATA ".................................#...............................#...."
DATA ".........................................................#............"
DATA ".................................................#...............#...."
DATA "..................#.....................#............................."
DATA ".#..............#.....................................#..............."
DATA "......................................................................"
DATA "....................#......................#.........................."
DATA ".......................................................#.............."
DATA "......#......#................#........................#.............."
DATA "...................#.................................................."
DATA "..............#.................#..........#...........#...........#.."
DATA "....................#................................................."
DATA "#....................................................................."
DATA "......................................................................"
Re: AI TANKS first draft
That is not my tank, that is your tank image.BasicCoder2 wrote:Latest version on rotating world around the agent which I hope you don't mind is the tank image from https://nr100.home.xs4all.nl/badidea/
If you do image_rotate and directly put, it is probably faster to use 'multiput'.
My intention for image_rotate was that you can pre-rotate images in memory.
-
- Posts: 3906
- Joined: Jan 01, 2009 7:03
- Location: Australia
Re: AI TANKS first draft
Oops. What appears to have happened is I downloaded your sprite but clicked another one in the download folder thinking it was the one I just downloaded!badidea wrote:That is not my tank, that is your tank image.
When I googled "tank sprite" images the tank sprite appears to be used by many others so I don't know its original source.