delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/2002/01/11/01:03:11

X-Authentication-Warning: delorie.com: mailnull set sender to djgpp-bounces using -f
From: "A. Sinan Unur" <asu1 AT cornell DOT edu>
Newsgroups: comp.os.msdos.djgpp
Subject: Re: allegro and math libraries
Date: 11 Jan 2002 05:58:52 GMT
Organization: Cornell University
Lines: 331
Sender: asu1 AT cornell DOT invalid (on pool-141-149-208-114.syr.east.verizon.net)
Message-ID: <Xns91939FA2EA6EASINANUNUR@132.236.56.8>
References: <5cp%7.332292$ez DOT 47656452 AT news1 DOT rdc1 DOT nj DOT home DOT com>
NNTP-Posting-Host: pool-141-149-208-114.syr.east.verizon.net
X-Trace: news01.cit.cornell.edu 1010728732 24122 141.149.208.114 (11 Jan 2002 05:58:52 GMT)
X-Complaints-To: usenet AT news01 DOT cit DOT cornell DOT edu
NNTP-Posting-Date: 11 Jan 2002 05:58:52 GMT
User-Agent: Xnews/L5
To: djgpp AT delorie DOT com
DJ-Gateway: from newsgroup comp.os.msdos.djgpp
Reply-To: djgpp AT delorie DOT com

"Zenko B. Klapko Jr." <zen1 AT comcast DOT net> wrote in
news:5cp%7.332292$ez DOT 47656452 AT news1 DOT rdc1 DOT nj DOT home DOT com: 

> For a week or two I've been trying to get a line to rotate like a
> propeller. I'm using the allegro and math libraries and I"m wondering
> what i'm doing wrong. I felt this would be a proper place for it since
> the programmers here are well educated and show concern for the people
> who post. And I've asked 3 math teachers (2 of which program) for help
> but to no avail. I've even tinkered with the equaitons and created
> really amazing cylinders and other circular based patterns, but I
> really would like a rotating line. Heres the Code and thanks for any
> time spent! -Zen PS. if you have a simpler example that will do.

I don't use allegro. In addition, I am a bit too lazy to try to figure out 
what the code below is doing. 

However, you should use constants M_PI, M_PI_2, and M_PI_4 defined in 
math.h for radian computations rather than your own approximations. Also, 
it doesn't look like you are erasing the lines after a short wait (which 
is what is needed to give the movement effect).

I put together a quick'n'dirty program which hopefully does something like 
what you want. doPropeller is where the relevant work gets done. The rest 
is there because I do not have allegro. It probably has a whole bunch of 
bugs.

compile it using

gcc -Wall -O proplr.c -o proplr.exe

then run it using

proplr 3, 14, 125

the first parameter is the speed of animation (smaller = faster).

/* === BEGIN: proplr.c === */
#include <dpmi.h>
#include <go32.h>
#include <stdio.h>  
#include <stdlib.h> 
#include <string.h> 
#include <sys/farptr.h>
#include <math.h>
#include <time.h>
#include <pc.h>

/* TODO: I really don't know the list of VGA modes */
typedef unsigned char COLOR;
typedef int VIDEOMODE;

typedef struct 
{
	int x;
	int y;
} POINT;

/* There does not seem to be a sign function in the standard library */

static int sign(int n)
{
    static int ret = 0;
    
    if (n != 0) ret = ( (n > 0) ? 1 : -1 );

    return ret;
}

VIDEOMODE setVideoMode(VIDEOMODE mode) 
{
    __dpmi_regs r;
    memset(&r, 0, sizeof(r));
    r.h.al = mode & 0xff;
	return __dpmi_int(0x10, &r) == 0 ? mode : -1;
}

VIDEOMODE getVideoMode(void)
{
    __dpmi_regs r;
    memset(&r, 0, sizeof(r));
    r.h.ah = 0x0f;
	__dpmi_int(0x10, &r);
	return r.h.al;
}

void pp13(POINT *p, COLOR c)
{
    _farpokeb(_dos_ds, 0xa0000 + 320*(p->y) + p->x, c);
    return;
}

/* use this version in loops where you are plotting a number
 * of pixels in succession. see info libc alpha far*
 */
 
void nspp13(POINT *p, COLOR c)
{
    _farnspokeb(0xa0000 + 320*(p->y) + p->x, c);
    return;
}

unsigned char gp13(POINT *p) 
{
    return _farpeekb(_dos_ds, 0xa0000 + 320*(p->y) + p->x);
}

unsigned char nsgp13(POINT *p)
{
    return _farnspeekb(0xa0000 + 320*(p->y) + p->x);
}

void drawVerticalLine(POINT *p, int dy, COLOR c)
{
	unsigned short old_sel = _fargetsel();
    
    _farsetsel(_dos_ds);
	{
		POINT r = { p->x, p->y };
		int i, sdy = sign(dy);
		for(i = 0; i != dy; i += sdy)
		{
			r.y = p->y + i;
			nspp13(&r, c);
		}
	}
    _farsetsel(old_sel);
    return;
}

void drawHorizontalLine(POINT *p, int dx, COLOR c) {
    unsigned short old_sel = _fargetsel();
    
    _farsetsel(_dos_ds);
	{
		POINT r = { p->x, p->y };
		int i, sdx = sign(dx);
		for( i = 0; i != dx; i += sdx)
		{
			r.x = p->x + i;
			nspp13(&r, c);
		}
	}
	_farsetsel(old_sel);
    return;
}

void drawLine(POINT *p1, POINT *p2, COLOR c) {
    int dx = p2->x - p1->x;
	int dy = p2->y - p1->y;

    /* handle vertical line */    
    if (dx == 0)
	{
        drawVerticalLine(p1, dy, c);
        return;
    }
    /* handle horizontal line */
    if (dy == 0)
	{
        drawHorizontalLine(p1, dx, c);
        return;
    }
    
    /* bad bad line drawing algorithm */
	{
		unsigned short old_sel = _fargetsel(); 
		double m = ((double) dy)/dx;
		
		_farsetsel(_dos_ds);
		
		if (fabs(m) <= 1)
		{
			POINT r;
			int i, sdx = sign(dx);
			for (i = 0; i != dx; i += sdx)
			{
				r.x = p1->x + i;
				r.y = (int) (p1->y + m*i);
				nspp13(&r, c);
			}
		}
		else
		{
			POINT r;
			int i, sdy = sign(dy);
			m = ((double) dx/dy);
			for (i = 0; i != dy; i += sdy)
			{
				r.x = (int)(p1->x + m*i);
				r.y = p1->y + i;
				nspp13(&r, c);
			}
		}
		
		_farsetsel(old_sel);
	}
    return;
}

void drawBox(POINT *b, POINT *e, COLOR c)
{
    drawVerticalLine(b, e->y - b->y, c);
    drawVerticalLine(e, b->y - e->y, c);
    drawHorizontalLine(b, e->x - b->x, c);
    drawHorizontalLine(e, b->x - e->x, c);
	return;
}

void drawFilledBox(POINT *b, POINT *e, COLOR c)
{
	int dx = e->x - b->x;
	int dy = e->y - b->y;
	
	if (abs(dx) > abs(dy))
	{
		POINT p = { b->x, b->y };
		int i, sdy = sign(dy);
		for (i=0; i != dy; i += sdy)
		{
			p.y = b->y + i;
			drawHorizontalLine(&p, dx, c);
		}
	}
	else
	{
		POINT p = { b->x, b->y };
		int i, sdx = sign(dx);
		for (i=0; i != dx; i += sdx)
		{
			p.x = b->x + i;
			drawVerticalLine(&p, dy, c);
		}
	}
	return;
}

void setBackgroundColor(COLOR c)
{
	POINT b = { 0, 0 };
	POINT e = { 320, 200};
	drawFilledBox(&b, &e, c);
	return;
}


void doPropeller(int speed, COLOR fg, COLOR bg)
{
#define NUM_POINTS 48
	static POINT begin[NUM_POINTS];
	static POINT end[NUM_POINTS];
	static const int LENGTH = 80;
	static const int X_CENTER = 160;
	static const int Y_CENTER = 100;
	static char INIT_DONE = 0;

	if (!INIT_DONE)
	{
		int i;
		const double STEP_ANGLE = M_PI/NUM_POINTS;
		begin[0].x = X_CENTER + LENGTH;
		begin[0].y = Y_CENTER;
		end[0].x = X_CENTER - LENGTH;
		end[0].y = Y_CENTER;
		
		for (i=1; i<NUM_POINTS; ++i)
		{
			begin[i].x = X_CENTER + (int) 
(LENGTH*cos(i*STEP_ANGLE));
			begin[i].y = Y_CENTER + (int) 
(LENGTH*sin(i*STEP_ANGLE));
			end[i].x = X_CENTER - (int) 
(LENGTH*cos(i*STEP_ANGLE));
			end[i].y = Y_CENTER - (int) 
(LENGTH*sin(i*STEP_ANGLE));
		}
		INIT_DONE=1;
	}

	while (!kbhit())
	{
		int i;
		unsigned long rawticks;
		for (i=0; i<NUM_POINTS; ++i)
		{
			if (kbhit()) break;
			drawLine(&begin[i], &end[i], fg);
			rawticks = rawclock() + speed;
			while(rawclock() < rawticks)
				__dpmi_yield();
			drawLine(&begin[i], &end[i], bg);
		}
	}			
	return;
}


/* test */
int main(int argc, char *argv[]) {
	int speed = 3;
	COLOR fg = 15;
	COLOR bg = 0;
	int old_mode;

	if (argv[1]) speed = atoi(argv[1]);
	if (argv[2]) fg = atoi(argv[2]);
	if (argv[3]) bg = atoi(argv[3]);
	
	{
		old_mode = getVideoMode();
		fprintf(stderr, "Current mode: %2.2x\n", old_mode);
		if ( 0x13 != setVideoMode(0x13) )
		{
			setVideoMode(old_mode);
			fprintf(stderr, "Could not set graphics mode: 
%2.2x\n", 0x13);
			exit(1);
		}
	}
	
	setBackgroundColor(bg);
	doPropeller(speed, fg, bg);

    setVideoMode(old_mode);
    
    return 0;
}
/* === END: proplr.c === */
-- 
--------------------------------
A. Sinan Unur
http://www.unur.com/

- Raw text -


  webmaster     delorie software   privacy  
  Copyright 2019   by DJ Delorie     Updated Jul 2019