⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 powers.c

📁 Microwindows genesis was with the NanoGUI project, and is now the primary distribution for both th
💻 C
字号:
/* * NanoBreaker, a Nano-X Breakout clone by Alex Holden. * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ *  * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. *  * The Original Code is NanoBreaker. *  * The Initial Developer of the Original Code is Alex Holden. * Portions created by Alex Holden are Copyright (C) 2002 * Alex Holden <alex@alexholden.net>. All Rights Reserved. *  * Contributor(s): *  * Alternatively, the contents of this file may be used under the terms * of the GNU General Public license (the  "[GNU] License"), in which case the * provisions of [GNU] License are applicable instead of those * above.  If you wish to allow use of your version of this file only * under the terms of the [GNU] License and not to allow others to use * your version of this file under the MPL, indicate your decision by * deleting  the provisions above and replace  them with the notice and * other provisions required by the [GNU] License.  If you do not delete * the provisions above, a recipient may use your version of this file * under either the MPL or the [GNU] License. *//* powers.c contains functions related to power-ups and power-downs. */#include <stdio.h>#include <stdlib.h>#include <nano-X.h>#include <nxcolors.h>#include "nbreaker.h"/* Called to activate the WideBat power-up. */void activate_widebat(nbstate *state){	/* Start the widebat timer: */	state->powertimes.widebat = state->poweruptime;		/* Cancel the NarrowBat power-down timer: */	state->powertimes.narrowbat = 0;	/* Set the new bat size: */	change_bat(state, LARGEBAT);}/* Called to activate the SlowMotion power-up. */void activate_slowmotion(nbstate *state){	/* Start the slowmotion timer: */	state->powertimes.slowmotion = state->poweruptime;	/* Cancel the FastMotion power-down timer: */	state->powertimes.fastmotion = 0;	/* Set the new ball velocity: */	state->ball.v = state->ball.sv;}/* Called to activate the StickyBat power-up. */void activate_stickybat(nbstate *state){	/* Start the stickybat timer: */	state->powertimes.stickybat = state->poweruptime;}/* Called to activate the PowerBall power-up. */void activate_powerball(nbstate *state){	/* Start the powerball timer: */	state->powertimes.powerball = state->poweruptime;}/* Called to activate the NarrowBat power-down. */void activate_narrowbat(nbstate *state){	/* Start the narrowbat timer: */	state->powertimes.narrowbat = state->powerdowntime;	/* Cancel the WideBat power-up timer: */	state->powertimes.widebat = 0;	/* Set the new bat size: */	change_bat(state, SMALLBAT);}/* Called to activate the FastMotion power-down. */void activate_fastmotion(nbstate *state){	/* Start the fastmotion timer: */	state->powertimes.fastmotion = state->powerdowntime;	/* Cancel the SlowMotion power-up timer: */	state->powertimes.slowmotion = 0;	/* Set the new ball velocity: */	state->ball.v = state->ball.fv;}/* Decrement a power timer, but don't allow it to go below 0. Returns the new * timer value if it was greater than or equal to 1 before the call, or -1 * if it was 0. You can detect the change from 1 to 0 by checking for the * function returning 0. */static int dec_power(int *i){	int tmp = *i - 1; /* Decrement the timer. */	if(tmp >= 0) *i = tmp; /* Store it unless it is < 0. */	return tmp; /* Return the result or -1 if the timer was 0. */}/* Called once per second by handle_timer_event() to decrement all the power * timers and cancel them when they reach 0. */void do_power_timers(nbstate *state){	/* If the "No PowerUp TimeOut" cheat is active, don't decrement the	 * power-up timers: */	if(!state->flags.nputo) {		/* Decrement the WideBat timer and set the bat size back to		 * the normal size if it exires: */		if(!dec_power(&state->powertimes.widebat))			change_bat(state, NORMALBAT);		/* Decrement the SlowMotion timer and set the ball velocity		 * back to the normal speed if it expires: */		if(!dec_power(&state->powertimes.slowmotion))			state->ball.v = state->ball.nv;		/* Decrement the StickyBat and PowerBall timers: */		dec_power(&state->powertimes.stickybat);		dec_power(&state->powertimes.powerball);	}	/* Decrement the NarrowBat timer and change the bat back to the normal	 * size if it expires: */	if(!dec_power(&state->powertimes.narrowbat))		change_bat(state, NORMALBAT);	/* Decrement the FastMotion timer and change the ball velocity back to	 * the normal speed if it expires: */	if(!dec_power(&state->powertimes.fastmotion))		state->ball.v = state->ball.nv;}/* Called from destroy_brick() to create a new power box of the specified type * centred on the specified location. */void new_power(nbstate *state, int type, int x, int y){	power *p, *pn;	sprite *s = state->powersprites[type];	/* Allocate the new power structure: */	if(!(p = malloc(sizeof(power)))) {		oom();		return;	}	/* Fill in the parameters: */	p->type = type;	p->y = y;	/* Calculate the left hand coordinate of the power box (the passed in	 * X coordinate specifies the centre, not the actual position): */	p->x = x - (s->w / 2);	/* Shift the box left or right if needed to make sure it is fully on	 * the screen: */	if(p->x < 0) p->x = 0;	if(p->x + s->w > state->canvaswidth)		p->x = state->canvaswidth - s->w;	p->next = NULL; /* This is the last in the list so there is no next. */	/* If the list is empty, make this power the head of the list: */	if(!state->powers) state->powers = p;	else {		/* Otherwise loop through until the end of the list: */		for(pn = state->powers; pn->next; pn = pn->next);		pn->next = p; /* Tag this power onto the end of the list. */	}	/* Draw the new power: */	draw_power(state, p, p->x, p->y, s->w, s->h);	/* Draw the modified area of the canvas to the output window: */	draw_canvas(state, p->x, p->y, s->w, s->h);}/* Draws all of the powers, limited to the specified rectangle, onto the * canvas. It is assumed that you have already redrawn the background and, if * necessary, the bricks under that area. */void redraw_powers(nbstate *state, int x, int y, int w, int h){	power *p;	sprite *s;	int px, py, pxx, pyy, pw, ph;	/* For each of the powers in the current powers list: */	for(p = state->powers; p; p = p->next) {		/* Find the sprite to use for this power type: */		s = state->powersprites[p->type];		/* Calculate the left hand side of the resulting area: */		if(x > p->x) px = x;		else px = p->x;		/* Calculate the top side of the resulting area: */		if(y > p->y) py = y;		else py = p->y;		/* Calculate the right hand side of the resulting area: */		if(x + w > p->x + s->w) pxx = p->x + s->w;		else pxx = x + w;		/* Calculate the bottom side of the resulting area: */		if(y + h > p->y + s->h) pyy = p->y + s->h;		else pyy = y + h;		/* Calculate the size of the resulting area: */		pw = pxx - px;		ph = pyy - py;		/* Only try to draw it if the resulting area is valid: */		if(pw > 0 && ph > 0) draw_power(state, p, px, py, pw, ph);	}}/* Unlinks the specified power structure from the list of powers. */void destroy_power(nbstate *state, power *p){	power *pp;	/* If this is the head of the list, shuffle it up by one: */	if(p == state->powers) state->powers = p->next;	else {		/* Find the previous entry in the power list: */		for(pp = state->powers; pp && pp->next != p; pp = pp->next);			/* Paranoid check to make sure we found it: */		if(!pp) {			fprintf(stderr, "Internal error: couldn't find "					"power in list in destroy_power()\n");			return;		}		/* Unlink it from the list: */		pp->next = p->next;	}	/* Free the power: */	free(p);}/* Called when a power box collides with the bat. Activates the relevant * power-up or power-down. */void power_collision(nbstate *state, power *p){	switch(p->type) {		case POWERW:			activate_widebat(state);			break;		case POWERS:			activate_slowmotion(state);			break;		case POWERT:			activate_stickybat(state);			break;		case POWERP:			activate_powerball(state);			break;		case POWERN:			activate_narrowbat(state);			break;		case POWERF:			activate_fastmotion(state);			break;	}}/* Called every animation frame to move all of the power boxes down and perform * collision detection, etc. Doesn't draw the results to the canvas unless the * power collides with something and is destroyed. */void animate_powers(nbstate *state){	sprite *s;	power *p, *pnext;	/* For each power in the list: */	for(p = state->powers; p; p = pnext) {		/* Remember the next item first, because we may destroy this		 * power, and then it would be wrong to use the pointer to		 * find the pointer to the next one in the list: */		pnext = p->next;		/* Find the sprite for this power type: */		s = state->powersprites[p->type];		/* Clear the old power away: */		draw_background(state, p->x, p->y, s->w, s->h);		/* Redraw any bricks we may have accidentally erased: */		draw_bricks(state, p->x, p->y, s->w, s->h);		/* Move it down: */		p->y += state->powerv;		/* If it has reached the bottom of the screen: */		if(p->y + s->h > state->canvasheight) {			/* Copy the erased region to the screen: */			draw_canvas(state, p->x, p->y - state->powerv,							s->w, s->h);			/* Destroy the power structure: */			destroy_power(state, p);			/* Check if it will collide with the bat: */		} else if(p->y + s->h > state->canvasheight - state->batheight				&& p->x + s->w > state->batx -				(state->batwidths[state->bat] / 2) &&				p->x < state->batx +				(state->batwidths[state->bat] / 2)) {			/* Copy the erased region to the screen: */			draw_canvas(state, p->x, p->y - state->powerv,							s->w, s->h);			/* Activate the relevant power: */			power_collision(state, p);			/* Destroy the power structure: */			destroy_power(state, p);		} else {			/* Redraw it in its new location: */			draw_power(state, p, p->x, p->y, s->w, s->h);		}	}	/* Redraw the ball in case we accidentally drew over it: */	redraw_ball(state);	/* Copy all the modified areas to the output window: */	for(p = state->powers; p; p = p->next)		draw_canvas(state, p->x, p->y - state->powerv, s->w,				s->h + state->powerv);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -