My First Fenix Project


xythen

Still Fresh
Joined
Jun 5, 2006
Messages
67
Age
36
Location
Scotland
Website
metalvania.blogspot.com
I finally decided to have a bash at coding in fenix, so I've been bumbling my way through various tutorials and source codes for about the past week. And, surprisingly, my first project is coming on quite well :) (better than I expected at least!) It's a remake/reworking of Cauldron II for the c64.

There are a few things I'm having problems with, so hopefully some of the gurus here can help!

Firstly, is it possible to have gapless looping of background music? I tried it using a short 1 second .ogg of pink noise using the following code:
CODE
intro_tune = LOAD_SONG("sounds\pink_noise.ogg");
PLAY_SONG(intro_tune,-1);

however this introduced a ~0.5 second delay between loops. Also, how do you stop playback so that you can initiate another song (such as when changing levels etc.)?

Another problem I'm having is to do with calling variables from a separate process. I've come across two code examples of how to do it, but neither of them seem to work. Here's what I tried:

CODE
process mapcalc();

private pumpID, pumpx, pumpy;

begin

pumpID=get_id(pumpkin_m(x,y));

loop
pumpx=pumpID.x;
pumpy=pumpID.y;
if (pumpx < 0)
signal(type ghost_1,s_kill);
end
end
end


where "pumpkin_m(x,y)" is the process I'm trying to get the variables "x" & "y" from. Any ideas what's going wrong?

I'm having lots of other problems with collision detections etc., but I think I need to rewrite my movement code before I get into that. :p

Thanks in advance!
 

ruckage

Certified Guru
Joined
Oct 15, 2006
Messages
659
Unfortunately I think the slight pause when a track loops is something we have to live with, I have noticed this myself but as far as I know there isn't a fix for it.

Music can be stopped by using the command stop_song, songs can also be faded in and out with fade_music_in and fade_music_off.

Not sure about the variable problem but try changing pumpID=get_id(pumpkin_m(x,y)) to pumpID=get_id(type pumpkin_m) . or alternatively get the pumpkin process to set a global variable to it's id number and reference that global variable, hope that makes sense :unsure:
 

ruckage

Certified Guru
Joined
Oct 15, 2006
Messages
659
sam fisher said:
should it not just be

CODE
pumpID=pumpkin_m(x,y);
as thats what I did when I used the cursor in my game in that way, a while ago.


I think if you do it that way it will actually create a new pumpkin_m process as well, I believe xythen just wants to get the id of an existing process.
 
Last edited by a moderator:

ruckage

Certified Guru
Joined
Oct 15, 2006
Messages
659
sam fisher said:
How shoould fenis know which process he means? There could be hundreds of pumpkin_m processes for all it knows.
Read my original reply and you may understand - Firstly there is only one pumpkin in cauldron 2 as far as I know so that wouldn't be a problem, secondly if there was more than one it would just return the id of the first and on successive calls return values of any other instances, thirdly I said to set a global variable to the id of the process and reference that if the previous method didn't work.
 
Last edited by a moderator:

WarmFluffyUK

The Big Wad Bolf.
Joined
Sep 4, 2004
Messages
3,384
Location
UK
Website
www.retrotech.one
Regarding the background music pausing during loop, what I do on my games is make a pause part of the music, i.e. have a big bit of reverb fade out one bar before the end of the ogg, and then loop back to the start. The gamer doesnt know anything has happened and it is much more seamless.
 

Quiest

I like turtles!
Joined
Sep 2, 2004
Messages
3,411
Age
38
Location
Dteuschland ;)
You have to assign the ID to a variable when calling a process:

CODE
pumpkin_id=pumkin(120,160);


then you can use it like that:

CODE
pumpkin_id.x
pumpkin_id.y
etc.


you can give processes local variable, just define them like globals, but put a local in front of it instead.
They work like .x, .y, etc for every process.

and don`t use pumpkin_id.x just like that,
make sure that the process still exists:

CODE
if( exists(pumpkin_id) )
if (pumpkin_id.x < 0) //use it directly, no need to store it in another variable first
signal(type ghost_1, s_kill); //kill all ghosts?
end;
end;


if you trying to get the ids of a process that exists more than once (i.e. gets called in a loop)
you can use get_id:

CODE
enemy_id=get_id(type enemy); //get id of first enemy
while( exists(enemy_id) )
if( enemy_id.y > 240 ) signal(enemy_id, s_kill); end;
enemy_id=get_id(type enemy); //get id of next enemy
end;


This is just an example, to do it like this would be stupid,
because you easily could just check in the enemy process if it falls off screen.
A good use would be when you are making homing missiles for
example, and you are trying to get the closest enemy.
 

YakumoFuji

Member
Joined
Sep 30, 2005
Messages
189
id love to see you get this working! cauldron 1+2 rocked so bad on the c64!! :) and they were two of the damn hardest games ever.

pumpkins revenge!!!
 

xythen

Still Fresh
Joined
Jun 5, 2006
Messages
67
Age
36
Location
Scotland
Website
metalvania.blogspot.com
thanks for all the replies! :)

I must have some syntax error somewhere as I still can't get it working. So at the moment I'm using ruckage's idea of just assigning the value to a global variable and reading it from there, which seems to be working fine for this situation.

I'm working on the collision detection now (which is a bit more complicated than I first thought cause the pumpkin has to always be bouncing), and I've ran across a problem in my fundamental understanding of how fenix works, which hopefully someone here can clear up for me. So my question is this:

Lets say you set fps=30. My understanding is that when the program runs, all process loops run simultaneously until the "frame;" function is reached, at which point it stops and waits for all processes to finish before starting them all again, doing this 30 times a second. Is this correct? If so, how do you know which point a particular process will have reached at any given moment in relation to another process? Do you have to use the "s_sleep", "s_freeze" and "s_wakeup" commands to sync the processes together? And does it also then not matter the order in which you call the processes in the main program?
 

ruckage

Certified Guru
Joined
Oct 15, 2006
Messages
659
How I believe Fenix works is that the processes a run one after the other stopping at a frame command, so once all processes have reached a frame command the processes are looped through again. So they do run 30 times per second if the framerate is 30fps but not all simultaneously.

You can define in what order the processes are executed though by use of the priority variable, this is a local variable and processes with a higher value are executed first.
 

xythen

Still Fresh
Joined
Jun 5, 2006
Messages
67
Age
36
Location
Scotland
Website
metalvania.blogspot.com
ruckage said:
How I believe Fenix works is that the processes a run one after the other stopping at a frame command, so once all processes have reached a frame command the processes are looped through again. So they do run 30 times per second if the framerate is 30fps but not all simultaneously.

You can define in what order the processes are executed though by use of the priority variable, this is a local variable and processes with a higher value are executed first.
Aha, I see. So does the priority variable work similarly to the z variable, having values from 1 to 255 with 1 being the highest priority?
 
Last edited by a moderator:

Quiest

I like turtles!
Joined
Sep 2, 2004
Messages
3,411
Age
38
Location
Dteuschland ;)
No, the higher the value, the higher the priority.
And neither priority nor z are limited from 1 to 255,
they can go the maximum integer range.

Instead of using globals (its a bad thing to have too much of em), you can also put the functionality of this:

CODE
process mapcalc();
private pumpID, pumpx, pumpy;
begin
pumpID=get_id(pumpkin_m(x,y));
loop
pumpx=pumpID.x;
pumpy=pumpID.y;
if (pumpx < 0)
signal(type ghost_1,s_kill);
end
end
end


right into you pumpkin_m process:

CODE
process pumpkin_m(x,y)
begin
...
loop
...
if (x < 0)
signal(type ghost_1,s_kill);
end;
frame;
end;
end;


If you create the pumpkin_m process in the mapcalc process,
what you wanted to do should work like this:

CODE
process mapcalc();
private
pumpID;
begin
pumpID=pumpkin_m(x,y); //the process gets created at x,y (0,0 in this case as x,y have no values yet)
loop
if (pumpID.x < 0)
signal(type ghost_1,s_kill);
end;
end;
end;
 

xythen

Still Fresh
Joined
Jun 5, 2006
Messages
67
Age
36
Location
Scotland
Website
metalvania.blogspot.com
Thanks Quiest! I was just going by this snippet as to the range of z values, but I guess it's out of date now.

I've been rewriting my program from scratch, and I've now included the process I was having problems with within another process. Using father.x and father.y seems to work fine, so that's it solved for now! :)

But I've encountered another strange occurrence in my quest for pixel-perfect collision detection.

First of all I created a small room with a 1 pixel wide perimeter and two platforms, as in the pic below:

debug2.png


Gravity pushes the pumpkin down until it hits something, detected using:

CODE
if(collision(type mapdraw))
mapcollision(SCREENX/2,SCREENY/2);
end


I then use the mapcollision process to calculate the pixel values at specific points around the pumpkin on a hardness map, like so:

debug1.png


CODE
process mapcollision(x,y);

local
int ct, cb, cl, cr, ctl, ctr, cbl, cbr; //c=collision,t=top,b=bottom,l=left,r=right
begin
graph=2;

cb = map_get_pixel(0,graph,father.x,father.y+10);
ct = map_get_pixel(0,graph,father.x,father.y-10);
cl = map_get_pixel(0,graph,father.x-10,father.y);
cr = map_get_pixel(0,graph,father.x+10,father.y);
ctl= map_get_pixel(0,graph,father.x-10,father.y-10);
ctr= map_get_pixel(0,graph,father.x+10,father.y-10);
cbl= map_get_pixel(0,graph,father.x-10,father.y+10);
cbr= map_get_pixel(0,graph,father.x+10,father.y+10);


Here's the problem: The sprite is 21x21 pixels, so father.x gets the x-value at the exact centre of the sprite. To get the right-hand side say, I just add 10 to it.

Now, if have the sprite as a block of solid colour this method works fine, but as soon as I use my pumpkin sprite (which extends the full 21x21 pixels with just the corners shaved off) the bottom detection stops working, while the top, right and left work fine. I discovered that by changing the father.y to +9 instead of +10 (1 pixel higher than it should be) it began working again.

This suggests that for some reason it isn't detecting a collision on the bottom row of pixels. Why would this be? There are definitely non-transparent pixels on the bottom row, and the other sides seem to work fine.

Any help with this would be much appreciated! :)
 

xythen

Still Fresh
Joined
Jun 5, 2006
Messages
67
Age
36
Location
Scotland
Website
metalvania.blogspot.com
well whatever the problem with the collisions was, I've managed to circumvent it by using a 21x21 pixel transparent image with a 1 pixel border that follows the pumpkin movement and is used for the collisions.

I never thought a damn bouncing pumpkin would cause me so much grief! :lol:
 
Top