Generic 2D game engine / DCBasic

If you have any questions on programming, this is the place to ask them, whether you're a newbie or an experienced programmer. Discussion on programming in general is also welcome. We will help you with programming homework, but we will not do your work for you! Any porting requests must be made in Developmental Ideas.
Post Reply
BlackAura
DC Developer
DC Developer
Posts: 9951
https://www.artistsworkshop.eu/meble-kuchenne-na-wymiar-warszawa-gdzie-zamowic/
Joined: Sun Dec 30, 2001 9:02 am
Has thanked: 0
Been thanked: 1 time

Generic 2D game engine / DCBasic

Post by BlackAura »

This is one of the things I've been working on recently. It's kind of an off-shoot from DCBasic - it's the back-end that handles stuff like graphics, (limited) object management, sound, input, filesystems, and so forth. I'm intending it to be usable from both C++ and Basic, as the Basic bit is just a wrapper around the C++ interface (with differences, of course).

Here's the tricky part - making it generic enough that you can use it to just just about any 2D game imaginable, without making it too hard to use, and without requiring the game programmer to do all the work. So, it's a pain in the ass, basically.

I have the graphics, sound, system interface, filesystem, resource management and so forth covered. You can drop stuff on the screen, move it around, and then write your own code to actually make it do something. That's where DCBasic and it's associated engine are currently, and that's fine if you want simple 80's style arcade games. I've already written a couple of clones of various arcade games in it without too much difficulty, so that works quite nicely. Needs a bit more design work, and it's neither as clean nor as flexible as I would like, but it's a decent enough start. The major problem is that the rendering system isn't abstracted enough, so you need two completely separate rendering paths, with bits and pieces strewn around the place, and it only gets worse if you want to start doing custom rendering. The sound system is similar - it's actually duplicated, once for the PC version and once for the DC version. That's not really a problem though, and I can sort that out easily enough.

However, I don't think it provides anywhere near enough additional functionality. For example, collision detection has to be done manually. Everything on the screen is an object. The system can't manage objects, movement, collisions, levels, or anything else automatically. You basically have to program the most difficult bits by yourself.

The real question is now "what the heck do I need to provide?", and the corollary "what don't I need to provide?"

I'm working under the assumption that basic arcade games, puzzle games, and really weird games just aren't going to use the additional stuff, because it's not relevant, so that basically leaves more complex arcade games, platformers, shooters, and so forth. It also means that it must be optional - if you don't want to use any of it, you don't need to.

That completely knocks out the idea of doing full object management, and dealing with movement, physics, and stuff like that in the engine. Anyway, it tends to be rather game-specific, and it's not hard to implement anyway. Even in Basic it's pretty easy to implement, so I'm just not going to bother. On to what I think does need to be added.

I need some way to load and manipulate levels. I could use simple tile maps, but I think they're probably too limiting. Thinking about the way most 3D games work, I think it would be a good idea to use geometry-based level data. Basically, the level consists of a load of polygons (textured appropriately), and can be loaded into a level object and positioned on screen. It would provide ways to query the contents of the level, run collision detection between objects and the level, and so forth. I think it should be possible to have levels composed (in whole or in part) of tiles as well, just because we can basically. Once out of the level editor, there's no real reason for the game to care if a level is made of geometry or tiles.

That will need a level editor, of course. It also needs some thought - exactly what capabilities do the levels need? Should they be simple, flat 2D, or should they be 2.5D (have a depth value). Is there any reason to support multi-layered tilemaps? Do we bother including background fluff, like skies, parallax scrolling layers, and whatever, or do we only include the actual bits of the level and leave the rest to the programmer? How would be keep track of where objects are supposed to be created? Do we even bother? Should we be able to load more than one level at a time? Should it be possible to dynamically create a new level in the game? Or even just the tilemap portions. Should it be possible to edit levels in-game, or are movable objects enough? And so on.

Second - decent character animation. What I've got now is alright, but nothing brilliant - just simple textures, which you can animate by changing what texture you're drawing. What I'd like to do is have some sort of composite sprite format - you can use multiple textures, possibly other bits of geometry as well, and use them to build full characters. Think of all the console games that built characters (usually large robots) out of smaller sprites. Stuff like Vectorman, for example. Because we have additional capabilities, like rotating and scaling graphics, we can do a far better job. You could have single textures (or parts of textures) for a character's arms, legs, hands, feet, body and head, and animate those like you would a 3D model. It should be possible to chuck interpolation in there too, so you could animate using keyframes at 10 frames per second, and the animation is played back at 60 frames per second, fully interpolated. That would also allow you to speed up or slow down the animations, which might be quite useful.

Again, that'd need an editor. This is probably more a question for artists (y'know - the guys who are actually likely to use this stuff), but is it worth the bother? Would a simpler format (a load of textures with frame timers, for example) be better? Would anyone actually use it? If so, what kind of features would be useful? What would be superfluous?

Also needs collision detection. I could use simple axis-aligned bounding boxes, and that's what I already have. It's enough if you've just got a load of textured quads flying around the screen, without rotating, or scaling, or anything like that. However, I think that's too limiting.

Every object (that's collidable - if it's intangible it's not worth the effort) should have a shape associated with it. Probably the most flexible one would be an arbitrary convex polygon. I already have code to detect if arbitrary convex polygons are overlapping each other, which takes rotation and scaling into account. That should probably be extended to deal with collisions while moving, rather than simple overlap tests, and it should be able to give more information about a collision - at what time it occurred, for example. Or the vector required to push two objects apart if they're already overlapping. Contact points. Things like that. In the case of level geometry, surface normals might be useful too (so you can tell what angle the floor is at, for example).

Would other shapes be useful? For example, it's possible to add in axis-aligned bounding boxes, oriented bounding boxes (ones that rotate and scale with the object), circles, ellipses, and similar. Doing this does complicate things a bit, and I've not really thought of a good way to fully abstract the shapes, so it basically devolves into writing a collision test for every possible combination (polygon vs polygon, polygon vs circle, polygon vs box, and so on). Is it even worth the bother? Boxes can be approximated easily enough using polygons. It's more computationally intensive, but does that really matter? It's not as if this is going to be stretching the Dreamcast's CPU unless you're throwing around thousands of objects.

Also might need ray -> object and ray->level intersection tests, which could be used for movement, for laser-type weapons, or whatever.

On that note, how should the level be collided with? The simplest way (if using geometry-based levels) would be to collide with any polygons. That's probably not a good idea - it might be better to have separation between the visible shape of a level, and the physical shape of the level. Also, it might be a good idea to have a concept of content types. For example, you could mark an area as water by sticking a polygon over it, and marking it as "water" rather than "solid". The game can detect that, and react accordingly. You'd have to be able to mask out content types when doing collision detection, of course.

And how do we deal with tilemap levels? Should be simply mark each tile as either solid or not solid (or water, or whatever)? That'd be fine if we only ever wanted square shapes on a tilemap level. What if we wanted a slope? Should we be able to define arbitrary shapes for a tile, and then collide against those? Should that be done on a per-tile basis, or a per-graphic basis, or what?

Is there anything else that'd be useful? Any other functionality that's common to 2D games that might better be handled by the engine rather than the game code?

And if anyone dares say "I think it's a brilliant idea", I'm going to kick them. Very hard. I want people to say "that's a stupid idea, because...", or "wouldn't it be better to...", or "what if I wanted to do...", or whatever. I'm trying to build something that's (hopefully) going to be useful to someone, so I'd like someone else's opinions on it. What sort of functionality would be useful for a game you might want to build with it?

And also, before anyone asks, I know that's a lot of stuff I mentioned. I'm not going to do it all in one go, of course. And I realise that I'm going to have to make some compromises to make it realistic to implement, and not insanely difficult to use. I just want to get some ideas. Plus writing this all out has helped me clarify a few of my own ideas already. I know some of the right questions at least. Now I just need to find the right answers...

Whew... Long post there. If anyone has the time and can be bothered to sort through my insane ramblings, then you deserve a medal or something.
doragasu
DCEmu Cool Poster
DCEmu Cool Poster
Posts: 1048
Joined: Thu May 16, 2002 5:01 pm
Location: Madrid, Spain
Has thanked: 0
Been thanked: 0

Post by doragasu »

WOW, REALLY IMPRESSIVE...

Too bad I can't help with it, it looks like you have considered a lot more things that I could ever think of...

If you finish this and provide also a level editor, this could give a huge impulse to the DC homebrewn, just look all mods that are coming for the limited BOR and now imagine something more flexible...
BlackAura
DC Developer
DC Developer
Posts: 9951
Joined: Sun Dec 30, 2001 9:02 am
Has thanked: 0
Been thanked: 1 time

Post by BlackAura »

Hmm...

That all looks somewhat familiar. They have a far better scripting language, they apparently have a full object manager / physics system / rigid body dynamics, and a few of the details are different. It makes me feel a bit more certain of the engine design at least - these guys certainly do know what they're doing.

One interesting thing their engine does is splits things into layers, and allows you to do things like collision detection only on object within a layer, or for all layers, and so on. It's an interesting abstraction anyway, and one that might be useful (at the cost of making things slightly more complex, although if you don't want to use it, I don't think you'd have to). It'd also be useful for the level editors - you could define multiple layers, and potentially have them scroll differently, possibly controllable from the game code. Of course, the way I'm implementing scrolling is a little unusual (instead of scrolling, I'm using a 2x2 translation matrix, which allows you to do scrolling, scaling, rotation, and all kinds of other warping effects, which makes parallax scrolling impossible to do automatically). Thinking about it, the layers thing might well be the answer to that - each layer could have it's own t-matrix, so you can do parallax scrolling by scrolling layers at different speeds. Still tricky, because I have a separation between a scene and a view of the scene (same thing as a camera, only 2D), and global transformations (like scrolling) are done by the view, not the scene. Still need some more thought on that one.

I wonder if it'd be possible to implement the object manager / physics system in Basic on top of the collision detection stuff? It'd probably make writing some kinds of games a lot easier.

(Adds "Basic code library to do common stuff" to list)

Also, a few pre-built game engines might be useful. Something you can take, bolt on additional (game-specific) code, and have a working game fairly quickly. Take the generic platform game engine, add code to make it your own, add artwork and level designs, and away you go. If I can make the editor(s) easily extensible, you could have a generic level editor, then a platform level editor, which you could customise yourself into an editor for your particular game...

(Adds "Lots of useful example code" to list)

Actually, I think I've worked out how to handle objects and stuff in the level editor - don't. At least, not directly. Add some kind of meta-data to the level editor. You don't put down objects - you put down placeholder tags, and other information. The game code can read this information, and use it to create the objects as it sees fit. A pre-built game engine could handle that by itself, but if you wanted to write your own, you could do whatever you wanted to with this information. If you had tags that actually represented objects, you could probably set up some kind of graphical representation in the level editor, so (for most games) the distinction is irrelevant.

Actually, that's a lot like the way Quake (and associated level editors) work. A little more generalised, but still...

It might be worth implementing the editors in Java, so I don't need to do a Linux version, then a Windows version, and nag someone else to do a Mac version. Should be fast enough - the rendering work is all going to be done using OpenGL anyway. Maybe Java2D is up to the task? I've been meaning to play around with that anyway.
doragasu
DCEmu Cool Poster
DCEmu Cool Poster
Posts: 1048
Joined: Thu May 16, 2002 5:01 pm
Location: Madrid, Spain
Has thanked: 0
Been thanked: 0

Post by doragasu »

Great ideas! Especially I consider extremely useful the idea of making some pre-built game engines, it would make it a lot easier to use. The easier it is, the more used will become. The main advantage of BOR is it's very easy, and that's the reason of all the mods. With pre built game engines you could do something really easy without discarding the power of a more flexible engine.
Warmtoe
DC Developer
DC Developer
Posts: 453
Joined: Thu May 16, 2002 8:29 am
Location: ice88's house
Has thanked: 0
Been thanked: 0
Contact:

Post by Warmtoe »

The engine that I put together which drives all of the games I've been working on (Joggle, DC-RTronic, Burger DC and others) treats everything as an 'item' - including sounds and text - I chose the word 'item' because its all written in C, there are no objects - although conceptually its the same.

I actually 'render' all of these objects in lists (which I think is similar to the concept you have of layers) and perform collision detection on these lists selectively - which sounds very much like your layers concept.

I guess the reason for saying this is to prompt the idea that you can 'render' non-graphical objects too, so, sounds, 'game events' - and objects can generate new objects (think of the generators in Gauntlet).

Anyway - I love the way this is sounding!
Warmtoe
DC Developer
DC Developer
Posts: 453
Joined: Thu May 16, 2002 8:29 am
Location: ice88's house
Has thanked: 0
Been thanked: 0
Contact:

Post by Warmtoe »

Oh - I read a little deaper into what you were saying about needing to 'load' levels. If you use the concept of layers that you mention (lists in my parlance) then you a level is simply a set of objects in a layer - so each level is represented by a file containing object instances and the layer to which they belong - again, this is how I've done it for Joggle DC-RTronic etc

I actually use separate lists for the 'visible' objects and 'collidable' shapes - so for example, the platforms on Burger DC are visible, but the collision detection between the characters and those platforms are not visible - they are objects whose 'rendering' is a no-op.
BlackAura
DC Developer
DC Developer
Posts: 9951
Joined: Sun Dec 30, 2001 9:02 am
Has thanked: 0
Been thanked: 1 time

Post by BlackAura »

I guess the reason for saying this is to prompt the idea that you can 'render' non-graphical objects too, so, sounds, 'game events' - and objects can generate new objects (think of the generators in Gauntlet).
You have a point there... I'm not really sure if it'd fit well into the design I have. It'd be dead easy if I were intending it to be used from C++ only, but it has to be usable from Basic as well, and there's not really any way I can handle game events or whatever as objects. Not in the graphics engine itself anyway.

If I were using C++ only, I'd simply allow you to create new classes derived from the generic game object type, and you could use that to implement game events, sound effects, generators, or whatever else. The C equivalent would be to store various function pointers, and have the engine call those each frame, or when a certain event happens (collisions, or whatever). However, there is no way I can derive a Basic object from a C++ object, and there is no way to call a method in a Basic object from C++ without breaking the Basic runtime. Severely. If I could find a better Basic interpreter than wxBasic, I'd jump on it...

That said, there's absolutely nothing preventing me from implementing that sort of thing in Basic, and as an addon in C++.
Oh - I read a little deaper into what you were saying about needing to 'load' levels. If you use the concept of layers that you mention (lists in my parlance) then you a level is simply a set of objects in a layer - so each level is represented by a file containing object instances and the layer to which they belong - again, this is how I've done it for Joggle DC-RTronic etc
Pretty much, yeah. However, since the objects that are created are non-interactive and have no behaviour of their own, I'm going to treat them separately in the engine itself, so I can use various optimisations (like organising things into trees, culling both the rendered objects and the potentially colliding objects) to allow more complex levels. That should be completely transparent to anyone using the engine.

Actually, nicking something from Quake, it might be a good idea to allow you to load active objects as well as passive objects. I'd need some way to query a loaded level for active objects (which would be treated like all normal objects), and grab a reference to them so the game can do something interesting with them.

Yet again, something that would be easier if I reversed the entire engine. A lot of the tricky bits only happen because I have the engine being controlled by a script (DCBasic), rather than the more usual other way around (game engine controlling everything, calling scripts for object behaviour). Of course, doing that would require a different programming language. And there's nothing stopping be from implementing a reversed engine on top of this one when it's finished.
I actually use separate lists for the 'visible' objects and 'collidable' shapes - so for example, the platforms on Burger DC are visible, but the collision detection between the characters and those platforms are not visible - they are objects whose 'rendering' is a no-op.
Good idea. I might nick that for the background stuff.

Just thinking... An automatic particle rendering thingy might be a good idea too. So you can spawn a load of particles, and have those automatically move around, fade out, or whatever. Good for explosions and the like. It'd also be a good idea to be able to have a particle generator object in the screen, so you can have particles spewing out of it.
User avatar
Christuserloeser
Moderator
Moderator
Posts: 5948
Joined: Thu Aug 28, 2003 12:16 am
Location: DCEvolution.net
Has thanked: 10 times
Been thanked: 0
Contact:

Post by Christuserloeser »

I'm really looking forward to this engine. :D
Insane homebrew collector.
Alexvrb
DCEmu Ultra Poster
DCEmu Ultra Poster
Posts: 1754
Joined: Wed Jul 17, 2002 11:25 am
Has thanked: 0
Been thanked: 0

Post by Alexvrb »

After reading that, I'm not entirely convinced it wouldn't be better just to have a boatload of game-enabling C/C++ libraries. Maybe down the road you can bundle it with tools to help beginners build something with it?
If you have twenty monkeys,
banging randomly on typewriters,
they will in twenty minutes produce the complete source code to World of Warcraft.
User avatar
Imerion
Mental DCEmu
Mental DCEmu
Posts: 349
Joined: Thu May 27, 2004 4:32 pm
Has thanked: 0
Been thanked: 0

Post by Imerion »

Thinking it through, I got some ideas. For the first thing, collision detection will be needed. That is a hard thing to do. Took me long time to learn proper ways of doing it. As for using polygons for tiles or characters and so on, it might be easier to make the engine handle full 3d. I know it was supposed to be a 2d game maker, but if everything is made up of polygons then you might as well do a 3d game engine, like Blitz Basic 3D or the even simpler DarkBasic. Since I have been programming basic my whole life, this really is a project I look forward to. Two other things which would be neat to see is support for groundfields (Mode 7...) and perhaps even raycasting functions. Like the old language DIV (which inspired Fenix). Also, Particle engines and such things do sound sweet, perhaps these things could come as libraries or addons later on. Don't know how important they are for a first release...
BlackAura
DC Developer
DC Developer
Posts: 9951
Joined: Sun Dec 30, 2001 9:02 am
Has thanked: 0
Been thanked: 1 time

Post by BlackAura »

For the first thing, collision detection will be needed.
Yep.
That is a hard thing to do. Took me long time to learn proper ways of doing it. As for using polygons for tiles or characters and so on, it might be easier to make the engine handle full 3d.
It's not that bad. It is pretty complicated, but as long as you have sufficient math background it's doable, although a bit boring. 3D polygon collision is much more difficult, and I wouldn't even attempt it (I'd either use simple bounding boxes, or a collision library like opcode).

I already have overlap testing between arbitrary polygons, complete with rotation and scaling, which is probably enough for most games. Certainly enough for simple arcade games (like Space Invaders, for example).

I still need to do collisions between moving objects, and line tracing. They need to return additional information like the time of collision, so I'm trying to come up with a clean way to do things. I might also add a couple of other primitives (bounding box, circle), and a flag to turn the rotation / scaling stuff on or off. That'd make it able to do just about anything.

The reason I'm not going to be doing 3D is that 2D is so much simpler (both for me, and anyone else using the thing), and I find 2D stuff more enjoyable to play around with. Things are only rendered as polygons, and I'm using polygons for collision because the objects can already be rotated and scaled, and it'd be stupid to have something that can rotate, but has a square bounding box...
Since I have been programming basic my whole life, this really is a project I look forward to.
Cool.
Two other things which would be neat to see is support for groundfields (Mode 7...) and perhaps even raycasting functions.
It would be slightly easier to add full 3D support. All of the internal math is 3D anyway (although it's not exposed to the Basic interpreter at all)

Actually... Since all the internal math is being done in 3D (except for collision detection, which is strictly 2D), it wouldn't be that hard to abuse it to do partial 3D graphics. It might be enough to do something like MarioKart anyway.

As for raycasting... probably not. Might be possible to simulate it.
Also, Particle engines and such things do sound sweet, perhaps these things could come as libraries or addons later on. Don't know how important they are for a first release...
A particle engine (along with the full animated sprites, and a few other bits) is possible to do in Basic. I'd rather do them in the engine though, because there are bits that I'm not exposing to Basic (like some internal data structures that are used to accelerate collision detections, drawing, and so on) that would make it both easier to implement, and faster too.

It's not going to be in the initial release though. A rough list:
  • PC version using SDL, OpenGL and (possibly) OpenAL - Windows, Mac, Linux
  • Dreamcast version using KGL
  • All basic graphical capabilities working
  • Simple sprites (a single texture, drawn on the screen)
  • Fonts
  • Strings database (for translations, and so on)
  • Controller input
  • Full collision detection
  • Filesystem access (using zip files)
  • Sound effects
  • Music
Later on:
  • Complex sprites
  • Arbitrary polygon sprites
  • Levels
    • Full polygon-based levels
    • Tilemaps
  • VMU saving
  • Particle system
  • Level editor, sprite editor, particle editor, other utilities
  • Paletted sprite support
Sir Savant
Somewhat Dumb Knight
Posts: 3653
Joined: Tue Oct 12, 2004 2:26 pm
Has thanked: 0
Been thanked: 0

Post by Sir Savant »

May I make a suggestion?

http://www.gamemaker.nl

Look at that engine, perhaps it would solve many of your questions on how things would be used, or even if they would be used.

As for a dreamcast version, do you mean a version where I can load the cd and start making games? As if editing games, saving to the vmu's, and uploading them to the net? I don't know if that sounds right. But I thought I might want to clear that up before someone else asked a similar question.

For filesystem access using zip files, what do you mean? I am just lost there.

Would the engine be freeware? Or would a later version come along with a price tag.

Great ideas, perhaps this could rival other game making engines. I would be more than happy to help make sample code to include in the releases. Basic platforming and rpg-type engines shouldnt be too hard as long as they are not all-encompassing.

For the actual editors, would they be in one package? Or would there be a level editor which would get graphics from the saved files of the graphics editor? Sorry if I sound so cryptic.
BlackAura
DC Developer
DC Developer
Posts: 9951
Joined: Sun Dec 30, 2001 9:02 am
Has thanked: 0
Been thanked: 1 time

Post by BlackAura »

May I make a suggestion?

http://www.gamemaker.nl

Look at that engine, perhaps it would solve many of your questions on how things would be used, or even if they would be used.
Completely different. I'm doing a lot of stuff that they aren't.
As for a dreamcast version, do you mean a version where I can load the cd and start making games? As if editing games, saving to the vmu's, and uploading them to the net? I don't know if that sounds right. But I thought I might want to clear that up before someone else asked a similar question.
No. The idea is that you develop (and test) the game on the PC, and then burn that on a CD with the Dreamcast version of the engine. Boot the CD, and it'll start the game. Or come up with a menu, if you've burnt more than one game on the CD.
For filesystem access using zip files, what do you mean? I am just lost there.
Instead of spewing files all over the CD, you can distribute a game as a single zip file. The engine can then load that zip file and let you read everything in it, and you don't even need to know that it's doing it. Accessing files inside a zip file is the same as reading files from the CD, or a hard disk (on the PC version).
Would the engine be freeware? Or would a later version come along with a price tag.
The Basic interpreter is under the GPL (and it's not my code, so I don't have any choice in the matter), so everything else will be released under the GPL as well. Which I would have done anyway - there's nothing there that I consider worth charging for. Anyway, I would like to (eventually) have ports for other systems that I can't develop myself (like a Mac version, or possibly a PS2 version), and I can't exactly ask someone else to do it if I'm charging money for it.

I might release the actual engine itself (without the Basic interpreter) under a BSD-style licence, if anyone wants to use it in a C++ game. The editors will be GPLed as well, and will be written in Java (so I don't have to write three separate versions).
Great ideas, perhaps this could rival other game making engines. I would be more than happy to help make sample code to include in the releases. Basic platforming and rpg-type engines shouldnt be too hard as long as they are not all-encompassing.
Well, I'm not sure about that. Not by itself anyway - it'd need quite a bit of additional stuff bolted on to be that easy to use.

Sample code would be appreciated. But I need to have something that actually works first...
For the actual editors, would they be in one package? Or would there be a level editor which would get graphics from the saved files of the graphics editor? Sorry if I sound so cryptic.
I'm using standard graphics formats, so there's really no need for a graphics editor. I don't know if the editors will all be in one program (I don't really think there's much point, since they all do separate things), but it wouldn't really be hard to write a single program that surrounds the lot of them. Considering that they all share much of the same code anyway...
Sir Savant
Somewhat Dumb Knight
Posts: 3653
Joined: Tue Oct 12, 2004 2:26 pm
Has thanked: 0
Been thanked: 0

Post by Sir Savant »

So, what are you using for code that you will add? I mean, what will the functions and stuff be called? Just wondering.
BlackAura
DC Developer
DC Developer
Posts: 9951
Joined: Sun Dec 30, 2001 9:02 am
Has thanked: 0
Been thanked: 1 time

Post by BlackAura »

I have an example program. It's actually pretty old (doesn't work anymore - I've re-organised a few things), but it's still close enough to the current version. Basically, it's a simple Space Invaders clone...

http://www.dcemulation.org/phpBB/viewto ... 1&start=22

There's also an old version of the reference manual in there (which I still haven't updated), which is incomplete and out of date anyway...

It should be enough to give you a general idea about how things work.
Post Reply