|
dchurch24
|
 |
« on: October 07, 2009, 11:32:12 AM » |
|
Hi all, Is there anyone who is willing to help a newbie with a side-scrolling game? I'm just making it for fun and to learn C#. I have some (badly drawn) sprites, and I have a background that I am scrolling, I have a count-down timer, a MPH speedometer etc... the accelleration seems to work, but I'm simply scrolling around the same continuous background. I need to know how to add obsticles that my motorbike sprite has to dodge/crash etc... So I guess I need some sort of tiling background so that I know where each sprite is? Screenshot: http://www.imagebam.com/image/5f5e9251481059I can post the code if someone is able to help me...I'm really stuck.
|
|
|
|
« Last Edit: October 07, 2009, 12:16:09 PM by dchurch24 »
|
Logged
|
|
|
|
|
Ed
|
 |
« Reply #1 on: October 07, 2009, 12:33:35 PM » |
|
Sure, go for it. If you're planning on sticking with the continuous rolling backdrop and just having something like "survive for x time/y distance without crashing" then it might be a bit easier to have the obstacles as independent sprite objects that move left with the velocity that the background is scrolling at. Otherwise you have to be moving the "camera" across a tilegrid type thing which I'd have to think a bit more about  Have you got some code that's trying to do something but not working? Or just the context that you're trying to put this stuff into?
|
|
|
|
|
Logged
|
|
|
|
|
dchurch24
|
 |
« Reply #2 on: October 07, 2009, 12:37:15 PM » |
|
Hi, thanks for the reply. I do have some code: using System.Drawing; using System; using System.IO;
using SdlDotNet.Graphics.Sprites; using SdlDotNet.Graphics; using SdlDotNet.Core; using SdlDotNet.Input; using SdlDotNet.Audio;
using System.Timers;
namespace sdl_scroller { class scroller { private Size size; private SpriteCollection sprites = new SpriteCollection(); private Surface surf = new Surface(400, 300); static int width = 400; static int height = 300; private Surface screen;
private String dir = "nothing"; private String sUpDown = "down"; private int iSpeed = 0;
private int iTimeleft = 120; private Sprite timerem;
bool decel = false;
private Sprite loading; private Sprite UpOrDown;
private Sprite bike;
SdlDotNet.Graphics.Font f2;
System.Timers.Timer timAcc; System.Timers.Timer timTime;
private MusicDictionary music = new MusicDictionary();
static void Main(string[] args) { scroller t = new scroller(); t.Go(); } public void timTime_Triggered(object source, ElapsedEventArgs e) { iTimeleft--; } public void timAcc_Triggered(object source, ElapsedEventArgs e) { if(decel==true){ if (iSpeed > 2) { iSpeed-=2; } else { dir = "nothing"; decel = false; iSpeed = 0; timAcc.Enabled = false; } }else{ if (iSpeed < 40) { iSpeed+=2; } } } private void Go() { SurfaceCollection floorTiles = LoadFloor(); screen = Video.SetVideoMode(width, height,false,false,false);
Events.Tick += new EventHandler<TickEventArgs>(this.Tick); Events.KeyboardDown += new EventHandler<KeyboardEventArgs>(Events_KeyboardDown); Events.KeyboardUp += new EventHandler<KeyboardEventArgs>(Events_KeyboardUp); Events.MusicFinished += new EventHandler<MusicFinishedEventArgs>(Events_MusicFinished);
timAcc = new System.Timers.Timer(); timAcc.Interval = 400; timAcc.Enabled = false; timAcc.Elapsed += new ElapsedEventHandler(timAcc_Triggered);
timTime = new System.Timers.Timer(); timTime.Interval = 1000; timTime.Enabled = true; timTime.Elapsed += new ElapsedEventHandler(timTime_Triggered);
// Place the background int rows = 8; int cols = 200; size = new Size(floorTiles[0].Size.Width * cols, floorTiles[0].Size.Height * rows);
for (int i = 0; i < cols; i++) { for (int j = 0; j < rows; j++) { // Create the sprite AnimatedSprite dw = new AnimatedSprite(floorTiles, new Point(i * floorTiles[0].Size.Width, j * floorTiles[0].Size.Height)); this.Sprites.Add(dw); } } f2 = new SdlDotNet.Graphics.Font("krem.ttf", 14); loading = new Sprite(f2.Render("Loading...", Color.White)); loading.X = 15; loading.Y = 15; loading.Z = -1;
f2 = new SdlDotNet.Graphics.Font("krem.ttf", 14); timerem = new Sprite(f2.Render(iTimeleft.ToString(), Color.White)); timerem.X = 15; timerem.Y = 28; timerem.Z = -1;
UpOrDown = new Sprite("down_arrow.gif"); UpOrDown.X = 355; UpOrDown.Y = 2; UpOrDown.Z = -1;
bike = new Sprite("bike.gif"); bike.X = 120; bike.Y = 355; bike.Z = -1; bike.Transparent = true; bike.TransparentColor = Color.FromArgb(0, 252, 0);
playMid();
Events.Run(); } private void playMid() { music["joy"] = new Music("joy.mid"); music["joy"].Play(true); } public virtual Surface RenderSurface() { surf.Fill(Color.Black); foreach (Sprite s in Sprites) { surf.Blit(s.Surface, s.Rectangle); } return surf; } protected static SurfaceCollection LoadFloor() { SurfaceCollection id = new SurfaceCollection(); //id.Add("d:\\data\\floor", ".png"); //Size sz = new Size(32 * 8, 32 * 5); Size sz = new Size(595, 300); id.Add("back2.png", sz); return id; }
public SpriteCollection Sprites { get { return sprites; } } private void Events_MusicFinished(object sender, MusicFinishedEventArgs e) { playMid(); }
private void Tick(object sender, TickEventArgs args) { screen.Fill(Color.Black); if (this != null) { screen.Blit(this.RenderSurface()); screen.Blit(loading); screen.Blit(UpOrDown); screen.Blit(bike); screen.Blit(timerem); } screen.Update(); foreach (Sprite s in Sprites) { switch (dir) { case "right": s.X = s.X - iSpeed; break; case "left": s.X = s.X + iSpeed; break; } surf.Blit(s.Surface, s.Rectangle); } if (sUpDown == "up") { UpOrDown = new Sprite("up_arrow.gif"); } else { UpOrDown = new Sprite("down_arrow.gif"); } UpOrDown.X = 355; UpOrDown.Y = 2; UpOrDown.Z = -1; UpOrDown.TransparentColor = Color.Red; UpOrDown.Transparent = true;
f2 = new SdlDotNet.Graphics.Font("krem.ttf", 14); String sSpeed = ((iSpeed * 10) / 4).ToString(); if (iSpeed > 39) { sSpeed = (((iSpeed * 10) / 4) + RandomNumber(0, 3)).ToString(); } loading = new Sprite(f2.Render("Speed: " + sSpeed + " mph", Color.White)); loading.X = 15; loading.Y = 14; loading.Z = -1;
timerem = new Sprite(f2.Render("Time Remaining: " + iTimeleft.ToString(), Color.White)); timerem.X = 15; timerem.Y = 31; timerem.Z = -1;
bike = new Sprite("bike.gif"); bike.X = 120; bike.Y = 188; bike.Z = -1; bike.TransparentColor = Color.FromArgb(0,252,0); bike.Transparent = true;
} private int RandomNumber(int min, int max) { Random random = new Random(); return random.Next(min, max); } private void Events_KeyboardDown(object sender, KeyboardEventArgs e) { switch (e.Key) { case Key.RightArrow: dir = "right"; //iSpeed = 1; decel = false; timAcc.Enabled = true; break; case Key.LeftArrow: dir = "left"; timAcc.Enabled = true; break; case Key.DownArrow: sUpDown = "down"; break; case Key.UpArrow: sUpDown = "up"; break; } } private void Events_KeyboardUp(object sender, KeyboardEventArgs e) { switch (e.Key) { case Key.DownArrow:
break; case Key.UpArrow:
break; case Key.RightArrow: // drop speed by one, as deceleration would occur faster. if (iSpeed > 2) { iSpeed = iSpeed - 2; } decel = true; break; case Key.LeftArrow: if (iSpeed > 1) { iSpeed = iSpeed - 2; } decel = true; break; } } } }
Files needed (I changed the code so it looks for them in the bin folder): http://www.cidb.co.uk/depends.rarI like the idea of having independent sprites that move into view. The other thing I'd like to be able to do is to have the 'road' move up and down - at the moment, the road (the bit with the brick background) is simply cut into the back2.png background image. Would I just create a background that's say, 12000 pixels long. I've been reading about 'tiling' but I can't seem to quite get my head around how that would work.
|
|
|
|
|
Logged
|
|
|
|
|
Jack Gleeson
|
 |
« Reply #3 on: October 07, 2009, 12:43:22 PM » |
|
As Ed said, have the obstacles as sprites themselves, not on a tile grid, there's no need at all. Scroll them left and when they move off the left side of the screen then change their position to the right side of the screen plus a random number but keep that within constraints so it doesn't get ridiculous. You should have your player as a class anyway so I think it's neater to seperate that into entity and then into player as a derived class so you can have your obstacles as another derived class. This lets you reuse all the code that would be in both so you only have to write it once.
It's easy enough to do, and I won't give you code because you're not going to learn that way, post here again if you still need help.
|
|
|
|
|
Logged
|
WebsiteFormerly known as ACardboardRobot.
|
|
|
|
dchurch24
|
 |
« Reply #4 on: October 07, 2009, 12:47:20 PM » |
|
Thank you both - that sounds fair to me ;-)
Just a quick question: Should I have the 'road' surface (the red brick in the above screenshot) as a single 32x32 sprite and read it's position from a text file so I get something like this:
0000000000000 0000000000000 1111110000000 0000002000000 0000000100000 0000000010000
(where 1 is the brick road, 2 is the curve as the road bends downwards etc...) ....and so on...
Is this the 'right' way to do it?
|
|
|
|
|
Logged
|
|
|
|
|
Jack Gleeson
|
 |
« Reply #5 on: October 07, 2009, 12:57:03 PM » |
|
I'm sorry, I don't really understand what you're saying. I think you're trying to say that you're going to have the character come down towards the real life player during that turn yes, so he's facing the monitor. Is that it?
|
|
|
|
|
Logged
|
WebsiteFormerly known as ACardboardRobot.
|
|
|
|
dchurch24
|
 |
« Reply #6 on: October 07, 2009, 12:59:39 PM » |
|
Not quite.
The character is travelling in a left to right direction along a track - the track can go up or down on it's Y axis and the character will travel up or down on the Y axis with it.
|
|
|
|
|
Logged
|
|
|
|
|
Jack Gleeson
|
 |
« Reply #7 on: October 07, 2009, 01:07:22 PM » |
|
That's what I was thinking would make more sense but the way you drew that diagram threw me off. So yeah, the way you're doing it now is probably the way I'd do it myself and have it loop when it reaches the end. To get the obstacles there, you might as well just have a tile grid the way you were going to do it firs, but maybe generate them each time the track loops so they're on the track but not in the same place. Only place a certain amount of them so the whole thing isn't taken up as well.
|
|
|
|
|
Logged
|
WebsiteFormerly known as ACardboardRobot.
|
|
|
|
dchurch24
|
 |
« Reply #8 on: October 07, 2009, 01:09:45 PM » |
|
Excellent, thanks.
Right - this time tomorrow I should have that part done (I hope).
|
|
|
|
|
Logged
|
|
|
|
|
Ed
|
 |
« Reply #9 on: October 07, 2009, 01:19:02 PM » |
|
I thought I was confused, and then I figured out what you meant, and now I'm confused again.
On your diagram there, what's going on when the road goes off the bottom of the map? Some non-traditional side-scrolling going on, or just a random example?
Anyway it sounds like tiles might be better if you want a true X mile long road that you race down... unless you're saying you want to give the scrolling background (like a band of paper on two rollers) and the background just moves up and down.... in which case... sprites.
But seems like you know what you gotta do, so good luck!
|
|
|
|
|
Logged
|
|
|
|
|
Jack Gleeson
|
 |
« Reply #10 on: October 07, 2009, 02:59:35 PM » |
|
I thought I was confused, and then I figured out what you meant, and now I'm confused again.
On your diagram there, what's going on when the road goes off the bottom of the map? Some non-traditional side-scrolling going on, or just a random example?
That screwed me up as well, he meant something like this: 0000000000000000 1111111000000000 0000000100000000 0000000011111111 0000000000000000 It's a change of the road's y position on a 2d plane.
|
|
|
|
|
Logged
|
WebsiteFormerly known as ACardboardRobot.
|
|
|
|
dchurch24
|
 |
« Reply #11 on: October 07, 2009, 03:03:31 PM » |
|
Yep - that's it.
So far, I have an array:
int[] iwall = new int[] { 1, 1, 1, 1, 2,4,4,4,4,4,4,3,1,1,1,1,1,1,2,4,4,4,4};
...which I will change to a lookup file.
1=straight wall 2=bend up 3=bend down 4=same as 1, but Y is changed to match the top of 2.
I hope that makes sense.
|
|
|
|
|
Logged
|
|
|
|
|
Jack Gleeson
|
 |
« Reply #12 on: October 08, 2009, 03:45:20 AM » |
|
Perfect sense. You're saying tile one will have a y value of, for example, 10, and 2 will have a y value of 5, yes? That's an odd way of doing it and not what I would have done but it does make a lot of sense. It will allow you to just scroll the background as a sprite and not a tile.
|
|
|
|
|
Logged
|
WebsiteFormerly known as ACardboardRobot.
|
|
|
|
dchurch24
|
 |
« Reply #13 on: October 08, 2009, 07:35:46 AM » |
|
Ha - yep, that's exactly what I meant - and indeed, what I now have done.
I don't really know any 'standard' ways of doing this stuff, and that just sounded like a half-decent way to do it.
In hindsight though, I wish I'd spent more time designing the sprites, as now I have sprites of varying hight and width to take into account.
I suppose I wanted to jump in at the deep end. It's been a steep learning curve over the last few days.
The code is 90% there now, so I'll tidy it up a bit and will post it up here soon.
PS. How DO people do side scrolling games if not this way?
|
|
|
|
|
Logged
|
|
|
|
|