Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Topics - Marcus

Pages: [1] 2 3
1
Libraries / GLOOM, a new raycaster library
« on: May 21, 2017 »
I'm working on a new raycaster library. Currently it's not even a library, just a big test program. I'm not quite sure what all the features will be yet, but if you look at the old Amiga game GLOOM (https://www.youtube.com/watch?v=Zq0la57PIVA) that's about what I'm aiming for.

The latest version is attached to this post.




2
Code snippets / Line/circle collision
« on: May 05, 2017 »
Experimented some with collision handling between a user controlled circle and some static and rotating lines. Was just making a test of how to handle some things in a 3D game. Usually I handle collisions WHILE moving an object, but here I do tests AFTER moving by "pushing" the circle away if there's an intersection.


Code: [Select]
import "Keycodes.lib"
import "Math.lib"

lines#[4][4]
lines[1][0] = 100.0
lines[1][1] = 100.0
lines[1][2] = 500.0
lines[1][3] = 300.0
lines[2][0] = 100.0
lines[2][1] = 100.0
lines[2][2] = 132.0
lines[2][3] = 400.0


circleX# = 100.0
circleY# = 200.0
circleR# = 32.0

set redraw off

lineA# = 0.0
do
dx# = 0.0
dy# = 0.0
if keydown(VK_LEFT) then dx# = dx# - 4.0
if keydown(VK_RIGHT) then dx# = dx# + 4.0
if keydown(VK_UP) then dy# = dy# - 4.0
if keydown(VK_DOWN) then dy# = dy# + 4.0
circleX = circleX + dx
circleY = circleY + dy

lineA = lineA + 1.0
lines[0][0] = 360.0 - cos(lineA)*160.0
lines[0][1] = 240.0 - sin(lineA)*160.0
lines[0][2] = 360.0 + cos(lineA)*160.0
lines[0][3] = 240.0 + sin(lineA)*160.0

lines[3][0] = 400.0 - cos(lineA*0.5)*100.0
lines[3][1] = 300.0 - sin(lineA*0.5)*100.0
lines[3][2] = 400.0 + cos(lineA*0.5)*100.0
lines[3][3] = 300.0 + sin(lineA*0.5)*100.0


' draw.
set color 0, 0, 0
cls

set color 255, 255, 255
for i = 0 to sizeof(lines, 0) - 1
draw line int(lines[i][0]), int(lines[i][1]), int(lines[i][2]), int(lines[i][3])
dx# = lines[i][2] - lines[i][0]
dy# = lines[i][3] - lines[i][1]
next

steps = 0
do
collision = false
for i = 0 to sizeof(lines, 0) - 1
if CLInt(circleX, circleY, circleR, lines[i][0], lines[i][1], lines[i][2], lines[i][3])
collision = true
endif
next
steps = steps + 1
until collision = false or steps = 4

set color 255, 255, 0
draw pixel int(circleX), int(circleY)
for i = 0 to 12
a1# = float(i)*360.0/12.0
a2# = float(i + 1)*360.0/12.0
x1 = int(circleX + cos(a1)*circleR)
y1 = int(circleY + sin(a1)*circleR)
x2 = int(circleX + cos(a2)*circleR)
y2 = int(circleY + sin(a2)*circleR)
draw line x1, y1, x2, y2
next

redraw
wait 16
until keydown(27, true)

function CLInt(&cx#, &cy#, cr#, lx1#, ly1#, lx2#, ly2#)
c#[] = [cx - lx1, cy - ly1]
l#[] = [lx2 - lx1, ly2 - ly1]
lineLen# = V_Size(l)
param#
' p is the clost point ON the line to c.
p#[] = V_ProjectGet2(c, l, param)

' is the projection on the line?
if param >= 0.0 and param <= lineLen
dv#[] = V_SubGet(c, p)
if V_Size(dv) < cr
' dv is actually the normal of the line in the correct direction.
' so we can get the corrected position.
_V_Normalize dv
cx = lx1 + p[0] + dv[0]*cr
cy = ly1 + p[1] + dv[1]*cr
return true
else
return false
endif
' check closest distance to vertices.
else
' closest to first vertex?
if param < 0.0
ed# = DistanceF(cx, cy, lx1, ly1)
if ed < cr
' push out.
dv#[] = [cx - lx1, cy - ly1]
_V_Normalize dv
cx# = lx1 + dv[0]*cr
cy# = ly1 + dv[1]*cr
return true
else
return false
endif
' cosest to second vertex.
else
ed# = DistanceF(cx, cy, lx2, ly2)
if ed < cr
dv#[] = [cx - lx2, cy - ly2]
_V_Normalize dv
cx# = lx2 + dv[0]*cr
cy# = ly2 + dv[1]*cr
return true
else
return false
endif
endif
return false
endif

endfunc

function V_ProjectGet2#[](&u#[], &v#[], &p#)
n#[] = V_NormalizeGet(v)
s# = V_Dot(u, n)
p = s
return [n[0]*s, n[1]*s]
endfunc

3
Code snippets / Some basic p2p stuff
« on: February 26, 2017 »
I started to write on a 2d multiplayer shooter thingy, might be interesting if you're experimenting with the p2p library but don't find the tick-tack-toe example funny enough :)

The "game" is pointless. Start the first instance and choose to create a lobby (Y), then start up to 3 other instances where you chose not to create a lobby (N). Each player can shoot bullets (left mouse button) and throw grenades (right mouse button). Move around with AWSD or arrow keys and aim with the mouse cursor. Everything one player does is transmitted to the others.

Code: [Select]
' ------------------------------------------------------------------------------
' 1234.
'
' chose to create a lobby (Y) for the first running instance, then start up to
' three more instances that connect to the first (N).
' ------------------------------------------------------------------------------

import "Keycodes.lib"
import "Speed.lib"
import "p2p.lib"

constant:
' transmit player position four (60/15) times every second.
TSMT_PLY_POS_TICKS 15

' players.
PLY_MAX_BULLETS 8
PLY_MAX_GRENADES 2

' p2p messages.
MSG_PLAYER_POS   16
MSG_PLAYER_SHOOT 17
MSG_PLAYER_BULLET_DIED 18
MSG_PLAYER_GRENADE 19

' player types. PLY_BOT only exists for server, will be PLY_REMOTE
' for client.
PLY_NONE   0
PLY_THIS   1
PLY_REMOTE 2
PLY_BOT    3

' player status.
PLY_STATE_NONE       0
PLY_STATE_CONNECTING 1
PLY_STATE_INGAME     2

' log.
MAX_LOG_MESSAGES 6
LOG_CHAT 1
LOG_INFO 2
LOG_GOOD 3
LOG_BAD  4

visible:
' server or client.
isServer = false

' players, bullets and grenades.
players?[4]
playerBullets?[4][PLY_MAX_BULLETS]
playerGrenades?[4][PLY_MAX_GRENADES]

' log.
vLog?[MAX_LOG_MESSAGES]

hidden:

set window 16, 16, 480, 270

if not P2P_Init() then _Error "Could not initialize the p2p library"

_ClearLog
_ClearPlayers

' setup this player.
randomize time()
players[0].type = PLY_THIS
players[0].state = PLY_STATE_INGAME
players[0].x# = float(rnd(width(primary)))
players[0].y# = float(rnd(height(primary)))
players[0].dx# = 0.0
players[0].dy# = 0.0
players[0].spd# = 2.0
players[0].aimX# = 0.0
players[0].aimY# = 1.0
players[0].a# = atan2(1.0, 0.0)
players[0].ticks = 0
players[0].id = -1

' create lobby or connect to localhost.
write "Create lobby? (Y/N) "
result$ = upper(rln$(1))
if result = "Y"
isServer = true
players[0].name$ = "Serverman"
if not P2P_CreateLobby("1234", players[0].name$, 0, false)
_Error "Could not create lobby"
endif
if not P2P_SearchClient()
_Error "Could not search for client"
endif
_Log "Lobby created", LOG_INFO
else
isServer = false
players[0].name$ = "Clientman"
if not P2P_Connect("localhost", players[0].name$)
_Error "Could not connect to lobby"
endif
_Log "Joined lobby", LOG_INFO
endif

set redraw off

do
_P2P_Update
_HandleMessages

for i = 0 to 3
_UpdatePlayer players[i]
next
_UpdatePlayerBullets
_UpdatePlayerGrenades
_UpdateLog

' draw.
set color 0, 0, 0
cls
for i = 0 to 3
if players[i].type and players[i].state = PLY_STATE_INGAME then _DrawPlayer players[i]
next
for i = 0 to 3
' bullets.
for j = 0 to PLY_MAX_BULLETS - 1
if playerBullets[i][j].type
draw rect int(playerBullets[i][j].x#) - 1, int(playerBullets[i][j].y#) - 1, 2, 2, true
endif
next
' grenades.
for j = 0 to PLY_MAX_GRENADES - 1
if playerGrenades[i][j].type
s = 4 + int(sin(playerGrenades[i][j].p#*180.0)*8.0)
x# = playerGrenades[i][j].sx#*(1.0 - playerGrenades[i][j].p#) + playerGrenades[i][j].dx#*playerGrenades[i][j].p#
y# = playerGrenades[i][j].sy#*(1.0 - playerGrenades[i][j].p#) + playerGrenades[i][j].dy#*playerGrenades[i][j].p#
draw rect int(x) - s/2, int(y) - s/2, s, s, true
endif
next
next

_DrawLog

redraw
_SPD_HoldFrame 60
until keydown(VK_ESC, true)

' ------------------------------------------------------------------------------
' handle p2p messages.
' ------------------------------------------------------------------------------
procedure HandleMessages()
pkg?
while P2P_Receive(pkg)
' connections.
if pkg.id = P2P_USER_CONNECTED
_AddPlayer pkg.usr, pkg.msg$
_Log pkg.msg$ + " joined the lobby", LOG_INFO
if isServer
if ServerFull()
_Log "Server is now full", LOG_INFO
elseif not P2P_SearchClient()
_Error "Could not search for another client"
endif
endif
elseif pkg.id = P2P_USER_DISCONNECTED
index = PlayerIndex(pkg.usr)
players[index].type = PLY_NONE
_Log pkg.msg$ + " left the lobby", LOG_INFO
elseif pkg.id = P2P_CONNECTION_LOST
_Error "Lost connection to lobby"
' player status.
elseif pkg.id = MSG_PLAYER_POS
index = PlayerIndex(pkg.usr)
_P2P_Decompose pkg.msg$
x = P2P_GetInt()
y = P2P_GetInt()
a = P2P_GetInt()
moving = P2P_GetInt()
players[index].wx# = float(x)
players[index].wy# = float(y)
players[index].a# = float(a)
players[index].aimX# = cos(float(a))
players[index].aimY# = sin(float(a))
players[index].mov = moving
' first update?
if players[index].state = PLY_STATE_CONNECTING
players[index].state = PLY_STATE_INGAME
players[index].x# = players[index].wx#
players[index].y# = players[index].wy#
endif
dx# = players[index].wx# - players[index].x#
dy# = players[index].wy# - players[index].y#
d# = sqr(dx*dx + dy*dy)
if d >= 32.0
players[index].x# = 0.5*(players[index].x# + players[index].wx#)
players[index].y# = 0.5*(players[index].y# + players[index].wy#)
endif
elseif pkg.id = MSG_PLAYER_SHOOT
' index, type, angle
index = PlayerIndex(pkg.usr)
_P2P_Decompose pkg.msg$
bulletIndex = P2P_GetInt()
playerBullets[index][bulletIndex].type = P2P_GetInt()
a = P2P_GetInt()
dx# = cos(float(a))
dy# = sin(float(a))
playerBullets[index][bulletIndex].x# = players[index].wx# + dx*16.0
playerBullets[index][bulletIndex].y# = players[index].wy# + dy*16.0
playerBullets[index][bulletIndex].dx# = dx
playerBullets[index][bulletIndex].dy# = dy
elseif pkg.id = MSG_PLAYER_BULLET_DIED
index = PlayerIndex(pkg.usr)
_P2P_Decompose pkg.msg$
bulletIndex = P2P_GetInt()
playerBullets[index][bulletIndex].type = 0
elseif pkg.id = MSG_PLAYER_GRENADE
index = PlayerIndex(pkg.usr)
_P2P_Decompose pkg.msg$
grenadeIndex = P2P_GetInt()
playerGrenades[index][grenadeIndex].type = P2P_GetInt()
dstX# = P2P_GetFloat()
dstY# = P2P_GetFloat()
playerGrenades[index][grenadeIndex].sx# = players[index].x#
playerGrenades[index][grenadeIndex].sy# = players[index].y#
playerGrenades[index][grenadeIndex].dx# = dstX
playerGrenades[index][grenadeIndex].dy# = dstY
playerGrenades[index][grenadeIndex].p# = 0.0
dx# = playerGrenades[index][grenadeIndex].dx# - playerGrenades[index][grenadeIndex].sx#
dy# = playerGrenades[index][grenadeIndex].dy# - playerGrenades[index][grenadeIndex].sy#
d# = sqr(dx*dx + dy*dy)
playerGrenades[index][grenadeIndex].spd# = 4.0/d
endif
wend
endproc

' ------------------------------------------------------------------------------
' clear players.
' ------------------------------------------------------------------------------
procedure ClearPlayers()
for i = 0 to 3
players[i].type = PLY_NONE
for j = 0 to PLY_MAX_BULLETS - 1
playerBullets[i][j].type = 0
next
for j = 0 to PLY_MAX_GRENADES - 1
playerGrenades[i][j].type = 0
next
next
endproc

' ------------------------------------------------------------------------------
' add player.
' ------------------------------------------------------------------------------
procedure AddPlayer(id, name$)
for i = 0 to 3
if players[i].type = PLY_NONE then break
next
if i > 3
_Error "No player slot available"
endif
players[i].type = PLY_REMOTE
players[i].state = PLY_STATE_CONNECTING
players[i].id = id
players[i].name$ = name
endproc

' ------------------------------------------------------------------------------
' server full.
' ------------------------------------------------------------------------------
function ServerFull()
for i = 0 to 3
if players[i].type = PLY_NONE then return false
next
return true
endfunc

' ------------------------------------------------------------------------------
' get index in 'players' array for player id.
' ------------------------------------------------------------------------------
function PlayerIndex(id)
for i = 0 to 3
if players[i].type and players[i].id = id then return i
next
_Error "Player not found"
endfunc

' ------------------------------------------------------------------------------
' update player.
' ------------------------------------------------------------------------------
procedure UpdatePlayer(&ply?)
if ply.type = PLY_THIS
_UpdateThisPlayer ply
elseif ply.type = PLY_REMOTE
_UpdateRemotePlayer ply
elseif ply.type = PLY_BOT
_UpdateBotPlayer ply
endif
endproc

' ------------------------------------------------------------------------------
' update this player.
' ------------------------------------------------------------------------------
procedure UpdateThisPlayer(&ply?)
' aim.
mx# = float(mousex())
my# = float(mousey())
dx# = mx - ply.x#
dy# = my - ply.y#
k# = 1.0/sqr(dx*dx + dy*dy)
ply.aimX# = k*dx
ply.aimY# = k*dy
ply.a# = atan2(ply.aimY#, ply.aimX#)

' movement.
dxi = 0
dyi = 0
moving = false
if keydown(VK_LEFT) or keydown("A") then dxi = dxi - 1
if keydown(VK_RIGHT) or keydown("D") then dxi = dxi + 1
if keydown(VK_UP) or keydown("W") then dyi = dyi - 1
if keydown(VK_DOWN) or keydown("S") then dyi = dyi + 1
if dxi or dyi
dx# = float(dxi)
dy# = float(dyi)
k# = 1.0/sqr(dx*dx + dy*dy)
ply.dx# = k*dx
ply.dy# = k*dy
moving = true
else
ply.dx# = 0.0
ply.dy# = 0.0
endif
ply.x# = ply.x# + ply.dx#*ply.spd#
ply.y# = ply.y# + ply.dy#*ply.spd#

' environment collision (will use Tilemap lib later on).
if ply.x# < 0.0 then ply.x# = 0.0
if ply.x# > float(width(primary)) then ply.x# = float(width(primary))
if ply.y# < 0.0 then ply.y# = 0.0
if ply.y# > float(height(primary)) then ply.y# = float(height(primary))

if ply.ticks = 0
_TransmitPlayerPosition ply, moving
endif
ply.ticks = (ply.ticks + 1)%TSMT_PLY_POS_TICKS

' shooting.
if mousebutton(0, true)
for i = 0 to PLY_MAX_BULLETS - 1
if playerBullets[0][i].type = 0 then break
next
if i < PLY_MAX_BULLETS
playerBullets[0][i].type = 1
playerBullets[0][i].x# = ply.x# + ply.aimX#*16.0
playerBullets[0][i].y# = ply.y# + ply.aimY#*16.0
playerBullets[0][i].dx# = ply.aimX#
playerBullets[0][i].dy# = ply.aimY#

_P2P_ComposePackage MSG_PLAYER_SHOOT
_P2P_AddInt i
_P2P_AddInt playerBullets[0][i].type
_P2P_AddInt int(players[0].a#)
_P2P_SendComposed
endif
endif
' throw grenade.
if mousebutton(1, true)
for i = 0 to PLY_MAX_GRENADES - 1
if playerGrenades[0][i].type = 0 then break
next
if i < PLY_MAX_GRENADES
playerGrenades[0][i].type = 1
playerGrenades[0][i].sx# = ply.x#
playerGrenades[0][i].sy# = ply.y#
playerGrenades[0][i].dx# = float(mousex())
playerGrenades[0][i].dy# = float(mousey())
playerGrenades[0][i].p# = 0.0

dx# = playerGrenades[0][i].dx# - playerGrenades[0][i].sx#
dy# = playerGrenades[0][i].dy# - playerGrenades[0][i].sy#
d# = sqr(dx*dx + dy*dy)
playerGrenades[0][i].spd# = 4.0/d

_P2P_ComposePackage MSG_PLAYER_GRENADE
_P2P_AddInt i
_P2P_AddInt playerGrenades[0][i].type
_P2P_AddInt int(playerGrenades[0][i].dx#)
_P2P_AddInt int(playerGrenades[0][i].dy#)
_P2P_SendComposed
endif
endif
endproc

' ------------------------------------------------------------------------------
' update remote player.
' ------------------------------------------------------------------------------
procedure UpdateRemotePlayer(&ply?)
' must be ingame for updating.
if ply.state <> PLY_STATE_INGAME then return

dx# = ply.wx# - ply.x#
dy# = ply.wy# - ply.y#
d# = sqr(dx*dx + dy*dy)
if d > 0.0
k# = 1.0/d
ply.x# = ply.x# + dx*k*min#(d, 2.0)
ply.y# = ply.y# + dy*k*min#(d, 2.0)
if ply.mov
ply.wx# = ply.wx# + dx*k*2.0
ply.wy# = ply.wy# + dy*k*2.0
endif
endif

' environment collision (will use Tilemap lib later on).
if ply.x# < 0.0 then ply.x# = 0.0
if ply.x# > float(width(primary)) then ply.x# = float(width(primary))
if ply.y# < 0.0 then ply.y# = 0.0
if ply.y# > float(height(primary)) then ply.y# = float(height(primary))
endproc

' ------------------------------------------------------------------------------
' update bot player.
' ------------------------------------------------------------------------------
procedure UpdateBotPlayer(&ply?)
endproc

' ------------------------------------------------------------------------------
' transmit player position.
' ------------------------------------------------------------------------------
procedure TransmitPlayerPosition(&ply?, moving)
_P2P_ComposePackage MSG_PLAYER_POS
_P2P_AddInt int(ply.x#)
_P2P_AddInt int(ply.y#)
_P2P_AddInt int(ply.a#)
_P2P_AddInt moving
_P2P_SendComposed
endproc

' ------------------------------------------------------------------------------
' update player bullets.
' ------------------------------------------------------------------------------
procedure UpdatePlayerBullets()
for i = 0 to 3
' this player's bullets.
if i = 0
for j = 0 to PLY_MAX_BULLETS - 1
_UpdatePlayerBullet playerBullets[i][j], j
next
' remote bullets.
else
for j = 0 to PLY_MAX_BULLETS - 1
_UpdateRemotePlayerBullet playerBullets[i][j]
next
endif
next
endproc

' ------------------------------------------------------------------------------
' update grenades.
' ------------------------------------------------------------------------------
procedure UpdatePlayerGrenades()
for i = 0 to 3
for j = 0 to PLY_MAX_GRENADES - 1
if playerGrenades[i][j].type
_UpdateGrenade playerGrenades[i][j]
if i = 0 and playerGrenades[i][j].type = 0
' handle enemy collisions.
endif
endif
next
next
endproc

' ------------------------------------------------------------------------------
' update grenade.
' ------------------------------------------------------------------------------
procedure UpdateGrenade(&g?)
g.p# = g.p# + g.spd#
if g.p# >= 1.0
g.type = 0
endif
endproc

' ------------------------------------------------------------------------------
' update player bullet.
' ------------------------------------------------------------------------------
procedure UpdatePlayerBullet(&b?, index)
if b.type = 0 then return

b.x# = b.x# + b.dx#*8.0
b.y# = b.y# + b.dy#*8.0
if b.x# < 0.0 or b.x# >= float(width(primary)) or b.y# < 0.0 or b.y# >= float(height(primary))
b.type = 0
_P2P_ComposePackage MSG_PLAYER_BULLET_DIED
_P2P_AddInt index
_P2P_SendComposed
endif
endproc

' ------------------------------------------------------------------------------
' update remote player bullet.
' ------------------------------------------------------------------------------
procedure UpdateRemotePlayerBullet(&b?)
if b.type = 0 then return

b.x# = b.x# + b.dx#*8.0
b.y# = b.y# + b.dy#*8.0
endproc

' ------------------------------------------------------------------------------
' draw player.
' ------------------------------------------------------------------------------
procedure DrawPlayer(&ply?)
set color 255, 255, 255
x = int(ply.x#)
y = int(ply.y#)
draw rect x - 8, y - 8, 16, 16, true
draw line x, y, x + int(32.0*ply.aimX#), y + int(32.0*ply.aimY#)

set caret x, y - 32
center ply.name$
endproc

' ------------------------------------------------------------------------------
' clear log.
' ------------------------------------------------------------------------------
procedure ClearLog()
for i = 0 to MAX_LOG_MESSAGES - 1
vLog[i].type = 0
next
endproc

' ------------------------------------------------------------------------------
' add log message.
' ------------------------------------------------------------------------------
procedure Log(msg$, type)
for i = 0 to MAX_LOG_MESSAGES - 2
vLog[i] = vLog[i + 1]
next
vLog[MAX_LOG_MESSAGES - 1].txt$ = msg
vLog[MAX_LOG_MESSAGES - 1].type = type
vLog[MAX_LOG_MESSAGES - 1].a = 1024
endproc

' ------------------------------------------------------------------------------
' update log.
' ------------------------------------------------------------------------------
procedure UpdateLog()
for i = 0 to MAX_LOG_MESSAGES - 1
if vLog[i].type
vLog[i].a = vLog[i].a - 4
if vLog[i].a <= 0 then vLog[i].type = 0
endif
next

endproc

' ------------------------------------------------------------------------------
' draw log.
' ------------------------------------------------------------------------------
procedure DrawLog()
set caret 4, height(primary) - 4 - fheight(0)*MAX_LOG_MESSAGES
for i = 0 to MAX_LOG_MESSAGES - 1
if vLog[i].type
if vLog[i].type = LOG_CHAT;     set color 255, 255, 255, vLog[i].a
elseif vLog[i].type = LOG_INFO; set color 200, 200, 200, vLog[i].a
elseif vLog[i].type = LOG_GOOD; set color 0, 255, 0, vLog[i].a
elseif vLog[i].type = LOG_BAD;  set color 255, 0, 0, vLog[i].a
endif
wln vLog[i].txt$
else
wln
endif
next
endproc

' ------------------------------------------------------------------------------
' show error message and quit.
' ------------------------------------------------------------------------------
procedure Error(msg$)
set font 0
set color 0, 0, 0
cls
set color 255, 255, 255
set caret 0, 0
wln "ERROR: ", msg
redraw
wait 500
wait keydown
end
endproc

4
While looking at a bunch of half finished games, that used to work, I noticed that many of them caused weird runtime errors when compiled with the latest naalaa. I narrowed it down to the Speed library. Replacing the latest Speed library with an older one, from naalaa 5 even, removed the runtime errors.
   I will have a look at this and try to figure out what's going on.

5
Announcements / I'm not dead
« on: January 12, 2017 »
Hi,

Not much activity here, but I still want to point out that I'm still alive and still work on and use naalaa. Work has kept me really busy for a long while. Also, my mom was diagnosed with cancer early last year. It got worse and worse, and she passed away on January 1 :(  This has really prevented me from "coding for fun" and being active here. Hopefully some fun stuff will happen during 2017 though :)

6
Code snippets / Othello (Reversi)
« on: November 07, 2016 »
This is not meant as a game, just something I wrote to show someone how to do ... something :)  Maybe with some AI it would be ok, may fix that.

Edit  Sorry, it's commented in Swedish :3

7
Code snippets / Blue stuff
« on: November 07, 2016 »
Code: [Select]
import "Random.lib"
import "Speed.lib"

set window 32, 32, 700, 700, false
set redraw off

' Create brush.
brushImage = 1
create image 1, 31, 31
set image 1
set color 0, 0, 0
cls
for y = 0 to 30;
dy# = float(y - 15)
dysqr# = dy*dy
for x = 0 to 30
dx# = float(x - 15)
d# = sqr(dx*dx + dysqr)
if d < 15.0
c = int(32.0*(1.0 - d/15.0))
set color c, c, c
set pixel x, y
endif
next
next
set image primary

curveCount = 32
curves#[curveCount][3][4]
for i = 0 to curveCount - 1
curves[i][0][0] = 0.5*float(width(primary)) - 15.0
curves[i][0][1] = 0.5*float(height(primary)) - 15.0
curves[i][1][0] = RandomFloat(float(width(primary))) - 15.0
curves[i][1][1] = RandomFloat(float(height(primary))) - 15.0
curves[i][1][2] = curves[i][1][0] - 15.0
curves[i][1][3] = curves[i][1][1] - 15.0
curves[i][2][0] = RandomFloat(float(width(primary))) - 15.0
curves[i][2][1] = RandomFloat(float(height(primary))) - 15.0
curves[i][2][2] = curves[i][2][0] - 15.0
curves[i][2][3] = curves[i][2][1] - 15.0
next

particleCount = 400
particles?[particleCount]
for i = 0 to particleCount - 1
particles[i].c = RandomInt(curveCount)
particles[i].p# = RandomFloat(1.0)
particles[i].s# = 0.005 + RandomFloat(0.005)
next

curveChangeTimer = 0
set color 0, 32, 64
cls

shouldDraw = true
do
curveChangeTimer = curveChangeTimer - 1
if curveChangeTimer <= 0
curveChangeTimer = 60
for i = 0 to curveCount - 1
if RandomInt(2) = 0
curves[i][1][2] = RandomFloat(float(width(primary))) - 15.0
curves[i][1][3] = RandomFloat(float(height(primary))) - 15.0
endif
if RandomInt(4) = 0
curves[i][2][2] = RandomFloat(float(width(primary))) - 15.0
curves[i][2][3] = RandomFloat(float(height(primary))) - 15.0
endif
next
endif

for i = 0 to curveCount - 1
curves[i][1][0] = curves[i][1][0]*0.99 + curves[i][1][2]*0.01
curves[i][1][1] = curves[i][1][1]*0.99 + curves[i][1][3]*0.01
curves[i][2][0] = curves[i][2][0]*0.99 + curves[i][2][2]*0.01
curves[i][2][1] = curves[i][2][1]*0.99 + curves[i][2][3]*0.01
next

if shouldDraw
for i = 0 to particleCount - 1
particles[i].p# = particles[i].p# + particles[i].s#
if particles[i].p# >= 1.0
particles[i].p# = particles[i].p# - 1.0
particles[i].c = RandomInt(curveCount)
particles[i].s# = 0.005 + RandomFloat(0.005)
endif
c = particles[i].c
p# = particles[i].p#
b1# = (1.0 - p)*(1.0 - p)
b2# = 2.0*(1.0 - p)*p
b3# = p*p
particles[i].x# = b1*curves[c][0][0] + b2*curves[c][1][0] + b3*curves[c][2][0]
particles[i].y# = b1*curves[c][0][1] + b2*curves[c][1][1] + b3*curves[c][2][1]
particles[i].i = int(255.0*(1.0 - p))
next

set color 0, 32, 64, 24
cls
set additive true
for i = 0 to particleCount - 1
set color 64, 128, 255, particles[i].i
draw image brushImage, int(particles[i].x#), int(particles[i].y#)
next
set additive false
redraw
endif

shouldDraw = SPD_HoldFrameDraw(60)

until keydown(27, true)

8
Code snippets / Goggles
« on: October 01, 2016 »
For some reason goggles makes raycasting look more interesting. Also with some fake looking up and down. Maybe switch between different view modes, one showing ghosts and hidden stuff?


9
Code battle / Online Gorillas / Tanks
« on: August 31, 2016 »
I doubt we'll see much response here, because the low amount of active users. But I still wanna give this a shot, try and awaken the coding warriors that exist in all of us.


Does anyone here remember the old QBASIC game Gorillas (https://en.wikipedia.org/wiki/Gorillas_(video_game))? The most popular version of this genre today is probably WORMS. Anyhow, I thought about writing something similar, but as a two player online game. It thought of it as another example for the P2P extension. But rather than just coding it myself, I now invite everyone who's interested to give it a shot, and maybe we'll see some nice variations. The "battle" ends in two weeks, that is Wednesday September 14.

Asking for any kind of help, even code examples, in this thread is NOT a crime - au contraire!

10
Code snippets / Better sky for the raycaster
« on: August 22, 2016 »
Alright, I wrote some lines of code for rendering an image to the inside of a cylinder. This might produce a bit fancier sky effects for raycaster games. I have not yet tested the code in combination with raycasting, a bit busy here tonight. But download the attachment and have a look. If it works well, I'll include the code in the raycaster library so that you can simply set an image to be used.

Here's the code (it's also in the zip together with a test image):

Code: [Select]
' Sky cylinder.

set window 32, 32, 640, 360

' Load a sky image. This image can be of any size. The image will be mapped to
' the inside of a cylinder.
load image 1, "sky.png"

' Field of view.
fov# = 90.0

' Create some lookup tables.
w = width(primary)
h = height(primary)
hw = w/2
hh = h/2
unit# = float(hw)/tan(fov*0.5)
angleOffset#[w]
cylHeight[w]
for x = 0 to hw - 1
angleOffset[hw + x] = atan(float(x)/unit)
angleOffset[hw - 1 - x] = -angleOffset[hw + x]
cylHeight[hw + x] = int(float(h)/cos(angleOffset[hw + x]))
cylHeight[hw - 1 - x] = cylHeight[hw + x]
next

' Player's angle.
viewAngle# = 0.0

set redraw off

do
' Increase angle.
viewAngle = viewAngle + 1.0
_WrapAngle viewAngle

' Set alpha to 0, since the alpha channel represents the "fog density"
' when using the raster commands.
set color 255, 255, 255, 0

' Draw.
for x = 0 to w - 1
tileHeight = cylHeight[x]
a# = viewAngle + angleOffset[x]
_WrapAngle a
u# = a/360.0
draw vraster 1, x, hh - tileHeight/2, hh + tileHeight/2, u, 0.0, u, 1.0
next

redraw
wait 16
loop

procedure WrapAngle(&a#)
while a < 0.0; a = a + 360.0; wend
while a > 360.0; a = a - 360.0; wend
endproc


11
Code snippets / Write wave files
« on: August 18, 2016 »
Generates three sound effects, saves them as wave and then loads and plays them.

Code: [Select]
' ===============================================================================
' Write an 8 bit, 11025 Hz, wave file from data.
' ===============================================================================


import "Random.lib"

constant:
SAMPLE_RATE 11025

hidden:


' Duration in seconds.
duration = 1

' Data in float format [-1..1]
data#[SAMPLE_RATE*duration]


' Generate explosion sound.
vol# = 1.0
for i = 0 to sizeof(data) - 1
' Noise.
data[i] = (RandomFloat(2.0) - 1.0)*vol
' Fade out.
vol = vol - 1.0/float(sizeof(data))
next
' Write file
_WriteWave "noise.wav", SAMPLE_RATE, data


' Generate beep sound.
a# = 0.0
vol# = 1.0
for i = 0 to sizeof(data) - 1
' Sine.
data[i] = sin(a)*vol
a = a + 16.0
while a > 360.0; a = a - 360.0; wend
' Fade out.
vol = vol - 1.0/float(sizeof(data))
next
' Write file
_WriteWave "sine.wav", SAMPLE_RATE, data


' Generate ... weird sound.
a# = 0.0
b# = 0.0
vol# = 1.0
volIn# = 0.0
for i = 0 to sizeof(data) - 1
' Weird.
data[i] = sin(a)*volIn*vol
a = a + (1.0 + sin(b))*8.0
b = b + 0.5
while a > 360.0; a = a - 360.0; wend
while b > 360.0; b = b - 360.0; wend
' Fade out.
volIn = min#(volIn + 4.0/float(sizeof(data)), 1.0)
vol = vol - 1.0/float(sizeof(data))

next
' Write file
_WriteWave "weird.wav", SAMPLE_RATE, data



' Load the files.
load sound 0, "noise.wav"
load sound 1, "sine.wav"
load sound 2, "weird.wav"

' Play the sound effect when player presses the space bar.
set caret width(primary)/2, 8
center "[1]   Play explosion"
center "[2]   Play beep     "
center "[3]   Play weird    "
center
center "[Esc] Exit          "

do

if keydown("1", true) then play sound 0
if keydown("2", true) then play sound 1
if keydown("3", true) then play sound 2
wait 16

until keydown(27, true)


' ===============================================================================
' Write 8 bit wave file from float array [-1..1].
' ===============================================================================
procedure WriteWave(filename$, rate, &data#[])
rate = rate
create file 0, filename$, true
' Write header.
_WriteBytes 0, "RIFF"
write32 0, 44 + sizeof(data)
_WriteBytes 0, "WAVE"
_WriteBytes 0, "fmt "
write32 0, 0x10
write16 0, 1
write16 0, 1
write32 0, rate
write32 0, rate
write16 0, 1
write16 0, 8
_WriteBytes 0, "data"
write32 0, sizeof(data)
' Write data.
for i = 0 to sizeof(data) - 1
write8 0, 127 + int(data[i]*127.0)
next
free file 0
endproc

' ===============================================================================
' Write string as bytes.
' ===============================================================================
procedure WriteBytes(f, bytes$)
for i = 0 to len(bytes) - 1
write8 f, asc(mid(bytes, i))
next
endproc

12
Announcements / Version 0.9.7 released
« on: August 10, 2016 »
Release notes from the docs

  • Marcus is the main developer of NaaLaa again
  • P2P library added, for online multiplayer games
  • IFX library added, for realtime image manipulation effects
  • ScrollList library added
  • Fixed a bug in NED, where the caret would "randomly" jump up to the top of the current document
  • The ' character now works just like a rem statement
  • New examples from the NaaLaa forum added, by B+, Rick3137 and John Master

--

Except for the P2P and IFX examples (by me), the new examples are some picks from this forum:

  Score4 (game) by Rick3137
  Square Elimination (game) by B+
  Jigsaw (game) by John Master
  Rainbow Beat (demo) by B+
  Poly and Poly Again (demo) by B+
  Reoccuring Squares (demo) by B+

Thanks Rick, B+ and John for the programs, I hope it was ok of me to add them to the installation :)

I really wanted to add the Flappy game by B+, but I was unsure about the copyright for the assets in the game. Are the free to use and distribute? If so, I'll add it in the next update.

13
Showcase / Glowy Shooter (P2P test game)
« on: August 05, 2016 »
I hope some of you would be interested in testing this game in some few days :)  It's a bit more advanced than the previous P2P extension test.

https://youtu.be/LGDPwfOGVlU

I gotta fix a proper lobby screen and some other details before I need help testing it. If this game actually works well with four players, I'd say the P2P extension is complete :)

14
Libraries / Scroll List
« on: July 15, 2016 »
I needed a scrollable list thingy for lobbies, so I wrote this little library.

15
Libraries / Bug in raycaster
« on: June 29, 2016 »
I just found a bug in the raycaster library. Think I've had it happen before without investigating it. Anyhow, it will make your program crash when it occurs. It's doesn't occur if your map always has atleast 2 live "objects".

If you've messed about with the library yourself, you can just add the following line

Code: [Select]
if rc_ObjCount <= 1 then return
to the very beginning of procedure RC_SortObjects. Else you can copy the lib file attached to this post to your N6/bin/libs folder.


Edit  Forgot to add the files ...




Pages: [1] 2 3