📄 draw.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. *//* draw.c contains functions for drawing the various game objects. */#include <stdio.h>#include <stdlib.h>#include <nano-X.h>#include <nxcolors.h>#include "nbreaker.h"/* Tiles the background image onto the canvas over the rectangle specified by * x, y, w, and h. This could probably be done more efficiently, but it works * and doesn't seem to use a lot of CPU time. */static void draw_tiled_background(nbstate *state, int x, int y, int w, int h){ int tilex = 0, tiley = 0, fromx, fromy, cx, cy; int destwidth, destheight, srcwidth, srcheight, cwidth, cheight; int dwidth = state->canvaswidth; int dheight = state->canvasheight; int swidth = state->background->w; int sheight = state->background->h; /* Clip the width of the background image to the size of the canvas * if necessary. */ if(swidth > dwidth) srcwidth = dwidth; else srcwidth = swidth; if(sheight > dheight) srcheight = dheight; else srcheight = sheight; /* For each row of tiles: */ for(;tiley < dheight; tiley += srcheight, tilex = 0) { /* If we've gone past the rectangle, return. */ if(tiley > (y + h)) return; /* If we haven't reached the rectangle, go to the next row. */ if(y > (tiley + srcheight)) continue; /* Clip the output to the bottom of the output window. */ if((tiley + srcheight) > dheight) destheight = dheight - tiley; else destheight = srcheight; /* For each tile in the row: */ for(;tilex < dwidth; tilex += srcwidth) { /* If we've gone past the rectangle, skip to the next * row. */ if(tilex > (x + w)) break; /* If we haven't reached the rectangle, skip to the * next tile in the row. */ if(x > (tilex + srcwidth)) continue; /* Clip the output size to the right side of the * output window. */ if((tilex + srcwidth) > dwidth) destwidth = dwidth - tilex; else destwidth = srcwidth; /* If the tile X dimension is completely within the * output rectangle, set the clipping to the full * size of the background image. */ if((tilex >= x) && ((tilex + destwidth) <= (x + w))) { fromx = 0; cx = tilex; cwidth = destwidth; } else { /* Not completely in the output rectangle. */ /* If necessary, clip off the left part of * the rectangle. */ if(x > tilex) { fromx = x - tilex; cwidth = destwidth - fromx; } else { /* Otherwise clip off the right part * of the rectangle. */ fromx = 0; cwidth = x + w - tilex; } /* Clip it to the size of the output area. */ if(cwidth > w) cwidth = w; /* Clip it to the size of the output window? */ if(cwidth > destwidth) cwidth = destwidth; /* Calculate the start of the area to copy * from. */ cx = tilex + fromx; } /* As above but for the Y dimension. */ if((tiley >= y) && ((tiley + destheight) <= (y + h))) { fromy = 0; cy = tiley; cheight = destheight; } else { if(y > tiley) { fromy = y - tiley; cheight = destheight - fromy; } else { fromy = 0; cheight = y + h - tiley; } if(cheight > h) cheight = h; if(cheight > destheight) cheight = destheight; cy = tiley + fromy; } /* If the output size is non-zero after clipping, copy * it to the canvas. */ if((cwidth > 0) && (cheight > 0)) { GrCopyArea(state->canvas, state->gc, cx, cy, cwidth, cheight, state->background->p, fromx, fromy, 0); } } }}/* Fill in the intersection of the two specified rectangles: */static void fill_in_rectangle(nbstate *state, int x, int y, int w, int h, int xx, int yy, int ww, int hh){ int xxx, yyy; /* Calculate the bottom right extents of the second rectangle: */ xxx = xx + ww; yyy = yy + hh; /* Intersect with the requested area: */ if(x > xx) xx = x; if(y > yy) yy = y; if(x + w < xxx) xxx = x + w; if(y + h < yyy) yyy = y + h; /* Calculate the size of the resulting area: */ ww = xxx - xx; hh = yyy - yy; /* If the result is greater than zero in size, draw it: */ if(ww > 0 && hh > 0) GrFillRect(state->canvas, state->gc, xx, yy, ww, hh);}/* Draw the background image in the middle of the canvas over the rectangle * specified by x, y, w, and h. */static void draw_centred_background(nbstate *state, int x, int y, int w, int h){ int bgx, bgy, xx, yy, ww, hh; /* Work out where to place the background image: */ if(state->background->w >= state->canvaswidth) bgx = 0; else bgx = (state->canvaswidth / 2) - (state->background->w / 2); if(state->background->h >= state->canvasheight) bgy = 0; else bgy = (state->canvasheight / 2) - (state->background->h / 2); /* If the area to copy intersects the area of the image: */ if(x < bgx + state->background->w && y < bgx + state->background->h && x + w > bgx && y + h > bgy) { /* Clip the start of the region: */ xx = (x > bgx) ? x : bgx; yy = (y > bgy) ? y : bgy; /* Clip the end of the region: */ ww = (x + w < bgx + state->background->w) ? x + w - xx : bgx + state->background->w - xx; hh = (y + h < bgy + state->background->h) ? y + h - yy : bgy + state->background->h - yy; /* Copy the background image. */ if(ww > 0 && hh > 0) GrCopyArea(state->canvas, state->gc, xx, yy, ww, hh, state->background->p, xx - bgx, yy - bgy, 0); } /* We fill in the rest of the canvas area black: */ GrSetGCForeground(state->gc, GR_COLOR_BLACK); /* Fill in the top rectangle: */ fill_in_rectangle(state, x, y, w, h, 0, 0, state->canvaswidth, bgy); /* Fill in the left rectangle: */ fill_in_rectangle(state, x, y, w, h, 0, bgy, bgx, state->background->h); /* Fill in the right rectangle: */ fill_in_rectangle(state, x, y, w, h, bgx + state->background->w, bgy, state->canvaswidth - bgx + state->background->w, state->background->h); /* Fill in the bottom rectangle: */ fill_in_rectangle(state, x, y, w, h, 0, bgy + state->background->h, state->canvaswidth, state->canvasheight - bgy + state->background->h);}/* Draw the background image onto the canvas over the rectangle specified by * x, y, w, and h. */void draw_background(nbstate *state, int x, int y, int w, int h){ if(state->backgroundtiled) draw_tiled_background(state, x, y, w, h); else draw_centred_background(state, x, y, w, h);}/* Draw the splash sprite (if there is one) in the centre of the canvas. */void draw_splash(nbstate *state){ if(!state->splash) return; GrCopyAreaAlpha(state->canvas, state->gc, state->splash->a, (state->canvaswidth / 2) - (state->splash->w / 2), (state->canvasheight / 2) - (state->splash->h / 2),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -