Enemies and Menu

A lot happened since last b-log. It didn't seem like it, but now that I look at it, I made quite a bit of progress.

Enemies'n'stuff

So last time I added the ability to shoot. Now, there will also be some targets to shoot at.

I still feel like this sounds like a job for OOP, so I started by defining 'TEnemyBase' inheriting from 'TEntityBase'. This will allow me to use the mystical powers of polymorphism to nicely stack all enemies together. While at it, I also added a bunch of procedures for applying basic operations on entire arrays of enemies at once.

Seeing that there will be a lot of different attacks, all possibly doing different things, I have also done the same thing for attacks. I do however have two lists, one for player and one for enemy attacks.

As far as actual enemies and their attacks go, they are mostly reused code from the player. The player attack even inherit directly from the player attacks, as they currently look the same. This is what I have now:

The enemies for now only stay in place and shoot at set interval. I will give them some AI later, but I'm still not sure what I want them to do. After some testing, free movement in 3 dimensions sounds cool on paper, but, at least for me, the controls are a bit too chaotic and confusing to focus on, especially when you also have to watch the rest of the field. Right now, you only move horizontally and vertically. That might be easier to deal with.

Enemies can be shot and killed. This uses their hitboxes. This led me to adding debug features. For now, you can press 'H' to toggle hitbox visibility.

As far as the collisions go, I was playing a bit with AI lately, so I asked copilot via CopilotChat.nvim to generate the collision detection. It gave me simple 'Axis-Aligned Bounding Box' algorithm. This algorithm is based on the fact, that for two boxes to collide, they have to intersect on all axis.

It saved me some time looking into collision algorithms, but it did not work straight out off the box. That's mainly because I do stuff a bit weirdly. It was simple to fix tho.

Yes, I do plan to continue using AI here and there. I do this project just for fun in my free time, so I don't see any problems with outsourcing the parts I don't want to focus on at the moment to AI. If you don't like it, feel free to go read something else.

A few more words to Pascal OOP

When you inherit from a virtual class and you change the number of arguments, for example, of the constructor, the compiler throws a bunch of warnings. I was not able to get rid of them, but they are just warning and cannot hurt you!

Inheritance works, but not for arrays. For example, if you have class 'Foo' and class 'Bar' inheriting from 'Foo'.

Then you declare 'procedure Baz(X: array of Foo);', you can't give it 'array of Bar'. I'm not sure if this is how most OOP languages work or not, but it's how Pascal does it and that's what matters now.

Project structure

I decided to alter the structure of the project. Mainly, I just grouped source files into directories. While compiling, fpc generates two extra files per unit, so I also made a special directory for them This all means that I could no longer just call fpc and make it handle stuff. So I made a simple script:

#!/bin/sh

command="fpc Main.pas -FUCompiled"

if [ $# -ne 1 ]; then
   echo "Usage:"
   echo "  compile.sh {-s|-d}"
   echo "     -s     link raylib statically"
   echo "     -d     link raylib dynamically"
   echo ""
   echo "Before recompiling in the other mode, run './clear.sh'"
   exit 1
fi

if [ $1 = '-s' ]; then
   command="$command -dSTATIC"
fi

for dir in $(ls -d */ | grep -o '[^/]*'); do
   command="$command -Fu$dir"
done

mkdir Compiled
eval $command

It basically collects all dirs in current folder and feeds them to fpc. Some might also notice that it takes some flags. Basically, the code can now link raylib both dynamically and statically. More on this later.

Menu

Since I didn't know what to do with enemies next, I just started working on the rest of the project. I added a main menu.

Menu is quite simple really. I have a list of entries, that are drawn on the screen. I added some sort of game state, that is handled in main. I use raylibs 'DrawRectangleGradientEx' to give the buttons some nice look, as it fits nicely with the overall vibe.

Most of the entries don't do anything as of now, but they will soon.

Compilations and MS Windows

So I was thinking. Both raylib and fpc have official Windows support. It should not be hard to compile the project on windows, right?

Well, I tried...

I installed the 32 bit windows fpc, as it does not distribute 64 bit version. Now to Raylib. The official installer only installed '.a' and '.so' files, probably for cygwin.

I was playing with different raylib distributions, until I eventually installed w64devkit, just as raylib recommends, but it didn't solve much. The mingw version of raylib does ship with actual '.dll' files.

Turns out I had to mess a bit with the bindings. I was messing with raylib a lot, so I don't know from where did it pick up raylib from, but you should not break anything by just throwing the libs next 'Main.pas'.

To make the compilation work, I have done the following:

{$MACRO ON}

INTERFACE

{$PACKRECORDS C}

{$ifndef WINDOWS}
  {$ifdef STATIC}
    // static raylib does not include 'libc' and 'libm'
    {$linklib c}
    {$linklib m}
    {$linklib raylib, static}
    
  {$else}
    {$linklib raylib}
  {$endif}
  
  {$define ext:=external}
  
{$else}
  {$define ext:=cdecl; external 'raylib.dll'}
{$endif}

Then I just put 'ext;' after all included functions. Yes, it does currently only compile for Windows dynamically, but if I ever distribute it, I can always just throw the '.dll' next to the '.exe'.

I also applied a bit of dark sorcery and instructed AI to translate the script to batch script.

@echo off
setlocal enabledelayedexpansion

set command=fpc Main.pas -FUCompiled

for /d %%D in (*) do (
    set command=!command! -Fu%%D
)

if not exist Compiled mkdir Compiled
%command%

Plans-p

Yes, actually.

I mainly want to fill out the missing menu items. Also some sound effects should be added.