Pixel-exact movement?

The place for codemasters or beginners to talk about programming any language for the Spectrum.
Post Reply
FFoulkes
Microbot
Posts: 161
Joined: Thu Feb 07, 2019 2:42 pm

Re: Pixel-exact movement?

Post by FFoulkes »

Well, this is not the way to go, and it's not what I was supposed to do. But I did it anyway (as I don't understand the rest yet):

Code: Select all

#include <arch/zx.h>
#include <math.h>

/* willy1.c
Compilation: 

zcc +zx -vn -lm -startup=0 -clib=sdcc_iy -zorg=32768 willy1.c -o willy1 -create-app */

#define PI 3.141592654
#define G 9.81
#define DT 0.02

typedef unsigned char byte;

byte willy[16] = {6, 62, 124, 52, 62, 60, 24, 60, 126, 126, 247, 251, 60, 118, 110, 119};

void clearWillyAt(byte x, byte y) {
    byte i;
    int *addr;
    for (i = 0; i < 16; i++) {
        addr = zx_pxy2saddr(x, y + i);
        *addr = 0;
    }
}

void plotWillyAt(byte x, byte y) {
    byte i;
    int *addr;
    for (i = 0; i < 16; i++) {
        addr = zx_pxy2saddr(x, y + i);
        *addr = willy[i];
    }
}

void blitWilly(byte x, byte y, int delaytime) {
    int u;
    plotWillyAt(x, y);
    for (u=0;u<=delaytime;u++) {
    }
    clearWillyAt(x, y);
}

float degreeToRadian(float degree)  {
    return degree / 180 * PI; 
}

float yPhysToYProg(float y_phys) {
    return -150 * y_phys + 80;
}

int main() {
    zx_cls(PAPER_WHITE);
    int x_prog = 120;
    float velocity = 3.0;
    float degree = 45.0;
    float vy;
    float y_phys;
    float y_prog;
    float y_start;
    int rounds;
    for (rounds = 0; rounds <= 10; rounds ++) {
        vy = velocity * sin(degreeToRadian(degree));
        y_phys   = 0.0;
        y_prog   = yPhysToYProg(y_phys);
        y_start  = y_prog;
        blitWilly(x_prog, (byte) y_prog, 30000);
        while(y_prog <= y_start) {
            vy       -= G * DT;
            y_phys   += vy * DT;
            y_prog    = yPhysToYProg(y_phys);
            blitWilly(x_prog, (byte) y_prog, 3000);
        }
        blitWilly(x_prog, (byte) y_prog, 30000);
    }
    return 0;
}
dfzx
Manic Miner
Posts: 682
Joined: Mon Nov 13, 2017 6:55 pm
Location: New Forest, UK
Contact:

Re: Pixel-exact movement?

Post by dfzx »

Well it all but redefines the word "inefficient" but at least it works. :lol:

How about pre-calculating those Y positions into a table of integers and using that in the animation loop?
Derek Fountain, author of the ZX Spectrum C Programmer's Getting Started Guide and various open source games, hardware and other projects, including an IF1 and ZX Microdrive emulator.
FFoulkes
Microbot
Posts: 161
Joined: Thu Feb 07, 2019 2:42 pm

Re: Pixel-exact movement?

Post by FFoulkes »

dfzx wrote: Mon Apr 27, 2020 9:54 am Well it all but redefines the word "inefficient" but at least it works. :lol:

How about pre-calculating those Y positions into a table of integers and using that in the animation loop?
You're right, that was rather inefficient. :roll: But now I check, if the sprite was already drawn at the pixel position and only redraw it, if not. It actually looks quite close to the real thing now, and I may be able to use the pixel positions as a blueprint for the animation. If I just want to print out the values, I even can use standard gcc on the PC:

Code: Select all

#include <arch/zx.h>
#include <math.h>

/* willy1.c
Compilation: 

zcc +zx -vn -lm -startup=0 -clib=sdcc_iy -zorg=32768 willy1.c -o willy1 -create-app */

#define PI 3.141592654
#define G 9.81
#define DT 0.003

typedef unsigned char byte;

byte willy[16] = {6, 62, 124, 52, 62, 60, 24, 60, 126, 126, 247, 251, 60, 118, 110, 119};

void clearWillyAt(byte x, byte y) {
    byte i;
    int *addr;
    for (i = 0; i < 16; i++) {
        addr = zx_pxy2saddr(x, y + i);
        *addr = 0;
    }
}

void plotWillyAt(byte x, byte y) {
    byte i;
    int *addr;
    for (i = 0; i < 16; i++) {
        addr = zx_pxy2saddr(x, y + i);
        *addr = willy[i];
    }
}

float degreeToRadian(float degree)  {
    return degree / 180 * PI; 
}

byte yPhysToYProg(float y_phys) {
    float a = -150 * y_phys + 80;
    return (byte) a;
}

int main() {
    zx_cls(PAPER_WHITE);
    byte x_prog = 120;
    float velocity = 3.0;
    float degree = 45.0;
    float vy;
    float y_phys;
    float y_start;
    byte y_prog;
    byte y_previous;
    int i;
    byte jumps;
    for (jumps = 0; jumps <= 10; jumps ++) {
        vy = velocity * sin(degreeToRadian(degree));
        y_phys   = 0.0;
        y_prog   = yPhysToYProg(y_phys);
        y_start  = y_phys;
        y_previous = y_prog;
        plotWillyAt(x_prog, y_prog);
        while(y_phys >= y_start) {
            vy       -= G * DT;
            y_phys   += vy * DT;
            y_prog    = yPhysToYProg(y_phys);
            if (y_prog != y_previous) {
                clearWillyAt(x_prog, y_previous);
                plotWillyAt(x_prog, y_prog);
                y_previous = y_prog;
            }
        }
        for (i = 0; i <= 30000; i++) {
        }
    }
    return 0;
}
dfzx
Manic Miner
Posts: 682
Joined: Mon Nov 13, 2017 6:55 pm
Location: New Forest, UK
Contact:

Re: Pixel-exact movement?

Post by dfzx »

I presume you don't need to be told what those floats are doing for the poor Z80? :)
Derek Fountain, author of the ZX Spectrum C Programmer's Getting Started Guide and various open source games, hardware and other projects, including an IF1 and ZX Microdrive emulator.
Post Reply