Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Basic Embedding
#1
I was playing around with Tilengine a little bit, but noticed that the input options were a touch on the limited side. At first, I thought this meant I wouldn't be able to use Tilengine for any of my projects. But then I noticed the embedding that was mentioned on the home page, and I started thinking.

After about an hour worth of experimenting, I was able to fire up a PyGame application, create a Tilengine instance, and get the Tilengine instance correctly rendering its output to a standard PyGame Surface. Now I can have access to all of the PyGame features that I'm used to working with, as well as the tile-map rendering that Tilengine provides. That put a big smile on my face.

I also started glancing over the C# binding for Tilengine, and giving my copy of Unity 3D some very meaningful looks. We'll see how far I can push this embedding thing, and how useful it can be in other contexts. I'll also see about maybe posting an example of the Python project that I started off with. It took a little poking, but it wasn't nearly as complicated as I thought it might be.
Reply
#2
That's very cool man, looking forward to hearing about any progress Smile
Reply
#3
I mentioned posting an example of what I came up with, and I do like to deliver. For any Python-heads out there, here you go...

Code:
import tilengine as tln
import pygame as pgm

#Time to handle the basic start-up code for the Tilengine
tEngine = tln.Engine.create(640, 480, 1, 0, 1)
tBack = tln.Bitmap.fromfile("beach.png") #I'm taking the beach image from the color-cycling example here, you can replace this with any other graphic image you have on hand.
tEngine.set_background_bitmap(tBack) #We're assuming your image is in the same folder, check the standard example projects if you require more advanced resource loading.

#We've got the basics of the Tilengine running, now it's time to fire up our basic PyGame
pgm.init()
pgm.display.set_caption("Tilengine Embed Trial")
pyScreen = pgm.display.set_mode((640, 480), pgm.RESIZABLE) #This fires up PyGame's basic rendering, and returns to us a PyGame Surface to work with. We're using the Resizable flag to test window resizing.

pyTargetRender = pgm.Surface((640, 480), 0, 32) #We have a reference to the screen, but now we want a placeholder Surface that we can use as a target for the Tilengine rendering
pyTargetRender.fill((98, 98, 98, 255)) #We'll fill the target area with a darker grey tone, just so it will stand out from the default background.

tEngine.set_render_target(pyTargetRender._pixels_address, 2560) #This is where the magic happens. We are taking our Tilengine object, and pointing its rendering to the placeholder Surface we created
#We're using the built-in _pixel_address reference in PyGame to retrieve a memory-address for the pixel-buffer of the placeholder Surface. That's what Tilengine needs to focus its rendering on the Surface.
#The number we're providing is for the scanline renderer. We get this number by taking the bit-depth of the Surface, dividing it by 8, and then multiplying it by the width of the target Surface.
#In this case we are getting 4 x 640, which is why we are using 2560. The bit-depth of our Surface is 32, which divided by 8 gives us 4. Keeping your target render width static will help.
#I'm planning on doing any scaling in PyGame, and not worrying about changing the Tilengine render resolution, so it should be fine.

gameRunning = True
while gameRunning:
   for pEvent in pgm.event.get():
       if pEvent.type == pgm.QUIT:
           gameRunning = False
   
   pyScreen.fill((0, 0, 0, 255)) #We'll fill the screen with standard black, which is a good start for frame refreshing
   tEngine.update_frame() #This is the standard function we use to update the Tilengine rendering, it will handle updating the current frame. Any frame-based game logic changes should happen before this.
   pyScreen.blit(pyTargetRender, (0, 0)) #And this is where we draw our placeholder framebuffer to the PyGame screen. Easy enough.
   pgm.display.flip() #A standard function to insure screen refreshing. This manually forces the display to update based on our defined changes.

#That pretty much covers it. A very basic application where we essentially embed Tilengine into a PyGame project. This replaces the stanard windowing within Tilengine with the PyGame windowing system.
#From this point forward, the majority of rendering will be handled by Tilengine. But we will still have access to standard PyGame rendering, as well as all of the other PyGame libraries.
#This includes PyGame input, as well as PyGame audio. You still get the rendering speed and tile-map support of Tilengine, but now you can also leverage the additional features of PyGame.

Please note, I haven't tested this out on a Raspberry Pi yet, only on a Windows machine. It worked just fine on that Windows machine, just note that I haven't given this a thorough wash on multiple platforms. I can't guarantee that it will work everywhere. That said, it works like a charm on Windows.
Reply
#4
Great work Richard! I'm glad you're playing a bit with tilengine, I hope that it's an interesting tool for your projects, and don't be afraid of asking for support if you get stuck somewhere. Documentation is not as developed as it should be.

It would be great to find an online platform to publish tutorials like yours about tilengine. Here inside the forum they won't get much attention, and that would be a shame because this is a very interesting one!
Reply
#5
Thanks, megamarc. I've got a few websites of my own. Some of this will probably find its way to those sites in the future, as more formal tutorials with some graphics and better writing. But time is limited, and I've got a lot on my plate, so I'm not really in any rush.

To be honest, one of the first things I thought of when poking around at Tilengine is that it would be a really great basis for developing some kick-ass point-and-click adventure games. I saw some of the color-cycling demos, and was struck by how low-res backgrounds could look so beautiful with the right palette animations. (and some phenomenal painting) When I started digging deeper into the code, I noticed that the input mapping for mouse support was limited in the bare-bones Tilengine windowing implementation. That's when I thought of wrapping Tilengine inside another engine, such as PyGame. I had already been playing around with PyGame, and had managed to cook up a custom scaling system for low-res games, as well as some basic mouse-management. With embedding of this style, I could easily use all of that work in conjunction with Tilengine.
Reply
#6
Hi Richard,

I've tried your sample that embed tilengine inside pygame, and it works. Cool!
At first I intended that tilengine would be just a rendering library, without any kind of windowing, intended to be embedded inside a bigger framework. But then I found that it would be too demanding for people starting to evaluate tilengine if I requested them to use (or build) their own framework. That would have put off many people. So I developed the built-in windowing as a way to ease initial evaluation and setup. I had in mind console/arcade games, the ones that used tiled graphics hardware: a virtual gamepad or arcade controls, CRT filters... Then some people found that te input layout was too limited, so I added the posibility to acces directly the underlying SDL2 input features. You could use any input method provided by SDL2 directly from the built-in windowing, but there isn't any sample that shows how to do this under the python wrapper, there is just a C sample.

I hope that you can continue developing your integration of pygame and tilengine!
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)