Demo Tutorial 2

Let’s get things moving shall we? In this tutorial I’m going to move that white dot we drew in the last tutorial around the screen!
The dot will follow coordinates generated by the sin and cos functions.

#include <math.h>
#include “ptc.h”

const SPEED=50;
const WIDTH=320;
const HEIGHT=200;

class Move_dot
{
  private:
    typedef struct count
    {
      int x;
      int y;
      int xdir;
      int ydir;
    } count;
    int32* sin_data;
    int32* cos_data;
    int frames;
    count current_pos;
    count last_pos;
    int dir;
    int last_counter;
  
    void update_counter (int* counter, int* dir)
    {
      if (dir[0] == 0) {
        if (counter[0] < 1024) {
          counter[0]++;
        } else {
          dir[0]=1;
        }
      } else {
        if (counter[0] > 0) {
          counter[0]–;
        } else {
          dir[0]=0;
        }
      }
    }
  public:
    Move_dot()
    {
      int index;
      sin_data = new int32[1024];
      cos_data = new int32[1024];
      for (float i=0; i < 360; i+=0.01) {
        index=(int)((i/360.0)*1024);
        sin_data[index]=(int)fabs(WIDTH*sin(i/-57.3));
        cos_data[index]=(int)fabs(HEIGHT*cos(i/-57.3));
      }
      frames=0;
      current_pos.x=150;
      current_pos.y=0;
      last_pos.x=150;
      last_pos.y=0;
      dir=0;
      last_counter=0;
    }

    ~Move_dot()
    {
      delete sin_data;
      delete cos_data;
    }

    void draw (int32 *buffer)
    {
        buffer[(int)((sin_data[last_pos.x])+(cos_data[last_pos.y]*WIDTH))]=0;
        buffer[(int)((sin_data[current_pos.x])+
          (cos_data[current_pos.y]*WIDTH))]=(255<<16)+(255<<8)+255;
        last_pos.x=current_pos.x;  
        last_pos.y=current_pos.y;  
        update_counter(&current_pos.x,&current_pos.xdir);
        update_counter(&current_pos.y,&current_pos.ydir);
        frames++;
    }
};
int main()
{
  try {
    int speed=SPEED;
    Move_dot move_dot;
The following is the Makefile you’ll use:

    // create format
    Format format(32,0x00FF0000,0x0000FF00,0x000000FF);

    // create console
    Console console;
    console.open(“tut02”,WIDTH,HEIGHT,format);

    // create surface
    Surface surface(WIDTH,HEIGHT,format);

    // loop until a key is pressed
    while (!console.key()) {

      if (speed == 0) {
        speed=SPEED;
        // lock surface
        int32 *buffer = (int32*) surface.lock();
  
        // draw dot
        move_dot.draw(buffer);
  
        // unlock surface
        surface.unlock();
  
        // copy to console
        surface.copy(console);
  
        // update console
        console.update();
      } else {
        speed–;
      }
    } // exit
    return 0;
  } catch (Error error) {
    // report error
    error.report();
  }
}

The following is the Makefile you’ll use:

# GNU Makefile for the X11 part of the PTC 2.0 C++ API
# Copyright (c) 1998 Christian Nentwich (brn@eleet.mcb.at)
# The PTC 2.0 C++ API is (c) 1998 Glenn Fiedler (ptc@gaffer.org)
# This package is licensed under the GNU LGPL
#
# Please refer to the file COPYING.LIB contained in the distribution for
# licensing conditions

include ../../Makefile.config

PROG1 = Tut02

all:  $(PROG1)

$(PROG1): $(PROG1).o
  $(CC) $(PROG1).o $(PTCLIB) $(PTC_X_LIBRARIES) -o $(PROG1)

.cc.o:
  $(CC) -c $(CFLAGS) $< clean:
  rm -f *.o

distclean:
  rm -f *.o
  rm -f $(PROG1)

Now compile Tut02.cc by typing make.
If you have previously compiled the example programs that came with PTC this should compile without problems.
Now run it from an xterm by typing:

./Tut02(return)
You should now see a window (or it will go fullscreen if your X server has such low resolutions) with a small white dot flying around it!
Press a key to escape out of the program.

How it works.

I’m not going to go back over the basic PTC stuff I covered in the previous tutorial. If you have any queries look at tutorial 1.

In my program I use 3 variables that never change. I defined these at the top of the program as constants:

const SPEED=50;
const WIDTH=320;
const HEIGHT=200;

The first constant, SPEED determines how often we refresh the screen. I have it set at 50 which works well on my machine. Change it and see what happens.
The last two figures should be self-explanatory. They are the width and height of the window we’ll create. These figures will also be used in generating our sin and cos values.
I used to wonder how I could code a demo in C++. “All those objects would get in the way”, I thought. Someone posted a message on CSIPD about a year or so ago voicing the same critisicm and among the replies was the idea that you put each demo part into a different class.
This is what I’ve done here. If I wanted to add a part to this small tutorial I would just code another class. With proper organisation I could create classes to do different functions of a demo part. Say, one class to move a scrolly and another class to draw and animate a logo or 3d object. All you would have to do is pass a pointer to the frame buffer to draw to!
“main” would probably take care of clearing the screen buffer at the end of each refresh, or another class could be called to record the changes to the frame buffer in-between calling each “action” class..
I’ve defined a Move_dot class here that contains all the code I need to draw and move my dot around the screen.
Inside the class I defined a struct to hold the details of the position of the dot as well as the direction (up or down) of the counter that runs through my sin and cos values. I also coded a small private function which either adds or subtracts 1 from the given counter and changes direction if necessary.
I decided to precalculate all my sin and cos values to speed up execution (precalc as much as possible!) and I needed two arrays to hold that data:

int32* sin_data;
int32* cos_data;

The class constructor, Move_dot(), creates my arrays for me, and fills the arrays with suitable values. It also defines various variables which I’ll use later on.
The class destructor, ~Move_dot(), on the other hand just deletes the two arrays freeing up the space they took.
The main function in the Move_dot class is the draw function.
It is called at every update to perform the animation on the white dot, and is the only public function in the class. It is called from the main loop of the program. It’s quite simple and should be easy to follow.

buffer[(int)((sin_data[last_pos.x])+(cos_data[last_pos.y]*WIDTH))]=0;

This line deletes the last drawn dot on the screen. We could just clear the whole buffer but this is much faster.

buffer[(int)((sin_data[current_pos.x])+(cos_data[current_pos.y]*WIDTH))]=(255< <16)+(255<<8)+255;

This line draws a white dot at some location on the screen.
The rest should be easy enough to decipher.
Mail me if you have problems.

Notes

Here’s a way to code demos in C++ which I touched upon above.
Code your demo parts as a series of classes. Each part should be contained in either one class or in a set of classes with suitable naming conventions.
i.e.

class part1_scroll
class part1_3dobj
class part1_music

class part2_vectors
class part2_dycp
class part2_music

If using the above you could set up PTC in “main” and create instances of each class and then call the draw function of each class. (or play of the music class.)
It’s probably advisable to let your “main” function clear the screen buffer after each refresh of video memory. Classes should just draw to the screen. They should not delete the previous image they drew (like my example above). This allows you to do nice things like implementing the “dirty rectangles” algorithm which just updates the parts of the screen which actually have been changed.
No, I’ve never done the above!

I've posted a new part in my …

I’ve posted a new part in my demo coding tutorial! Grab it at the Tutorial link on the side bar!

Check out the Linux Game Development Center. It’s a nice site with links to lots of tools, examples, projects and other nice game development stuff!

Update on Jan 1, 2008 linuxgames.org is gone. Grrr. It’s been taken over by a spammer.

On the day Slashdot links to m …

On the day Slashdot links to my page on Xoom the server decides to crash! Demonix is obviously now at lowrent.org. Now to stop all that spam from Xoom…
A new version of install-mail will be released soonish, but I guarantee nothing!
Check the “Linux Demo Ring” below. There are now 3 sites!
The PC Demo FanClub has moved yet again. Jer is also looking for people to provide content for his site. Click on “Join the Club” on his page for more details.

Have you ever tried to run dem …

Have you ever tried to run demos in dosemu or wine? I was thinking about creating a database of configurations required to run demos a few months back but I was sidetracked by exams and other such mundane happenings. Now I have the time and I was reminded about this by an email I received last night (It’s at home! Credits due when I get a chance!). I have some ambitious plans for a database that can be updated easily and daily with lists of working demos as well as configuration details.
Interested? Mail me at the address below!
On a seperate note, install-mail now has it’s own page. Check the side bar!

DemoNix may be moving shortly. …

DemoNix may be moving shortly. More news before it happens!
Bladeenc will be released in source form! It will be distributed under the LGPL. No news as to a release date at this time. The next version will hopefully have (among other features), STDIN/STDOUT support which will be very handy for all you script writers!
Check out Unload to turn your desktop into a MAC! It works quite well. Worth looking at!
New version of install-mail coming soon, as well as a page for it.
There’s been a plethora of music scene related tools coming out recently. There’s the GTK+ mod player mentioned in the last update as well as several other trackers and players appearing on freshmeat. Make sure your demo scene friends know about all these apps coming out!
I stumbled across the Triad homepage yesterday where I found two new demos by Triad for the C64! One is all about the Spice Girls while the other one looks _very_ similar to another demo, Red Storm, released by them a few years ago. Nice to see they’re still working on, and releasing C64 productions in 1998!
In preperation for the shutdown of Hornet, the PC Demo Fan Club has moved to a whole new site. No new demos mentioned though.

Demo Tutorial 1

This tutorial will be the first of a series I’ll write about creating demos. I’m going to start off with simple topics and introduce concepts and ideas you’ll need when coding graphics on a computer.

What’ll we do then?
I’m going to use the PTC library to demonstrate how to do graphical effects on your computer. I’m developing this tutorial on Linux so any instructions on compiling the example programs will obviously be for that platform. If anyone feels like contributing or changing anything please feel free to do so!
Before we get started you’ll have to download the PTC library from the link above. Do that now and click back to get back here when it’s downloading.
Unpack and compile the library somewhere (Make sure you read the INSTALL file. There are notes there on optimising the compilation.)
Assuming that all went well, change directory to the PTC “examples” directory and create a directory there called “tut01”.
What about writing a point to the screen? Cut and paste the following into a file called Tut01.cc in the tut01 directory.

#include “ptc.h”

int main()
{
    try {  
        // create format
        Format format(32,0x00FF0000,0x0000FF00,0x000000FF);
    
        // create console
        Console console;
        console.open(“tut01”,320,200,format);
    
        // create surface
        Surface surface(320,200,format);

        // loop until a key is pressed
        while (!console.key()) {
            // lock surface
            int32 *buffer = (int32*) surface.lock();
 
            // draw a white pixel at (160,100).
            buffer[160+100*320]=(255< <16)+(255<<8)+255;

            // unlock surface
            surface.unlock();

            // copy to console
            surface.copy(console);

            // update console
            console.update();
        }
        // exit
        return 0;
    } catch (Error error) {
        // report error
        error.report();
    }
}

The following is the Makefile you’ll use:

# GNU Makefile for the X11 part of the PTC 2.0 C++ API
# Copyright (c) 1998 Christian Nentwich (brn@eleet.mcb.at)
# The PTC 2.0 C++ API is (c) 1998 Glenn Fiedler (ptc@gaffer.org)
# This package is licensed under the GNU LGPL
#
# Please refer to the file COPYING.LIB contained in the
# distribution for licensing conditions

include ../../Makefile.config

PROG1 = Tut01

all: $(PROG1)

$(PROG1): $(PROG1).o

$(CC) $(PROG1).o $(PTCLIB) $(PTC_X_LIBRARIES) -o $(PROG1)

.cc.o:

$(CC) -c $(CFLAGS) $< clean:

rm -f *.o

distclean:

rm -f *.o

rm -f $(PROG1)

Now compile Tut01.cc by typing make.
If you have previously compiled the example programs that came with PTC this should compile without problems.
Now run it from an xterm by typing:

er see a small window with a white dot in the middle of it, or your screen will go black and a white dot will appear in the middle.
Press a key to escape out of the program

You’ve started on the road to creating a demo!

How it works.
(lots of info taken from the PTC Intro)
Format format(32,0x00FF0000,0x0000FF00,0x000000FF); – The Format class holds information about how pixels are composed. ie. 8 bit, 16 bit, 32 bit colour. The above code creates a 32 bit colour format.

Console console; – This is “your interface to the world. It contains the routines to access the framebuffer, and some simple keyboard routines.”

console.open(“tut01”,320,200,format); – This either opens a window or sets the screen resolution to 320 pixels across by 200 down. PTC will attempt to change screen colour depth to the closest one available to match your format.

Surface surface(320,200,format); – “A Surface is a memory area (in system memory, not in video memory) that you can draw into if you don’t want to draw directly to the screen.”
This command creates a 32 bit colour surface which is 320 pixels across and 200 pixels down

while (!console.key()) {

}

– While no key is pressed do the following…
When you lock the surface to write to it you get a pointer to it in memory. Then the program draws a single white pixel on it.
The surface is then unlocked, and copied to the console before the console is finally updated (meaning the image in “buffer” is drawn to the screen.

Notes

I presume you know how to code in C++. If you don’t you’ll be lost. Mail me if you want to know the _very_ basics and I’ll include some docs on that.
The above example was derived from examples in the PTC examples/ directory. Take a look there!
You do all your drawing to a special part of memory called a buffer. When all your drawing is finished that buffer is copied to the screen to be displayed. This way of drawing avoids the choppy updates you see in some demos and games where the image you see appears to update right in the middle of the screen.
The buffer you draw to is a 32 bit colour image of the screen. Even if your video mode isn’t 32 bit the conversion will be handled by PTC before it displays your buffer on the screen.
Make sure you read the docs on the PTC homepage. There isn’t much there, but it’s informative, and of course, you have the source code to the library to play with too. Make sure you take advantage of the “GPL” and learn from the code!

Want to code demos? I've star …

Want to code demos? I’ve started a tutorial on demo coding. If you’ve done any coding at all it won’t be anything new to you but for those others have a look. A knowledge of C++ is presumed, and is almost essential. Although I’m developing this in Linux, the code should compile just as well in Win32 with that platforms’ port of PTC.
Check the “Tutorials” link on the left side for more details!
Censor have a really nice site. Lots of screenshots of their old C64 stuff!
Also check out www.c64.com for lots of old C64 games!

Sad news. The Hornet archive w …

Sad news. The Hornet archive will soon close up shop and the Hornet group will disband. For those who don’t know, Hornet is probably the largest demo archive in the world but due to fading interest the group won’t continue to support the archive. There’s also an announcement available explaining what happened. The archive will be given over to scene.org so hopefully it will continue to exist.
As a final note, there are still Hornet CDs available. If you’re into demos it might be worth buying a copy of each.. I will.
I found a music tracker for Linux on freshmeat today.
Check out Sound Tracker which is described as a music tracker for the X window system. It looks promising.
Somehow by coincidence I come across another tracker for Linux. Have a look at Keg Tracker. Nice screenshot too!
Totally unrelated but interesting nevertheless. A friend discovered how to get access to any file on a WinNT machine even without being admin on the machine. Take a look at IE4 (Internet Options) and you might figure it out.. (This is probably an old hack but I haven’t heard about it before..)