void move_player(player_t* p, room_t* r, uint32_t dir) { // 0 = north, 1 = south, 2 = east, 3 = west switch(dir) { case 0: if(!is_solid(&r->map[p->pos.y - 1][p->pos.x])) p->pos.y -= 1; break; case 1: if(!is_solid(&r->map[p->pos.y + 1][p->pos.x])) p->pos.y += 1; break; case 2: if(!is_solid(&r->map[p->pos.y][p->pos.x + 1])) p->pos.x += 1; break; case 3: if(!is_solid(&r->map[p->pos.y][p->pos.x - 1])) p->pos.x -= 1; break; default: break; } }
/* * Wall cleanup. This function has two purposes: (1) remove walls that * are totally surrounded by stone - they are redundant. (2) correct * the types so that they extend and connect to each other. */ void wallification(int x1, int y1, int x2, int y2) { uchar type; register int x,y; struct rm *lev; /* sanity check on incoming variables */ if (x1<0 || x2>=COLNO || x1>x2 || y1<0 || y2>=ROWNO || y1>y2) panic("wallification: bad bounds (%d,%d) to (%d,%d)",x1,y1,x2,y2); /* Step 1: change walls surrounded by rock to rock. */ for(x = x1; x <= x2; x++) for(y = y1; y <= y2; y++) { lev = &levl[x][y]; type = lev->typ; if (IS_WALL(type) && type != DBWALL) { if (is_solid(x-1,y-1) && is_solid(x-1,y ) && is_solid(x-1,y+1) && is_solid(x, y-1) && is_solid(x, y+1) && is_solid(x+1,y-1) && is_solid(x+1,y ) && is_solid(x+1,y+1)) lev->typ = STONE; } } wall_extends(x1,y1,x2,y2); }
/* Create a turret */ static struct SpecialObj *make_turret(int x,int y,int type) { double a; struct SpecialObj *turret = malloc(sizeof(struct SpecialObj)); if(!turret) { perror(__func__); return NULL; } turret->gfx = turret_gfx[type==2]; turret->frames = turret_frames[type==2]; turret->type = type; turret->frame=0; turret->x = x; turret->y = y; turret->owner = -1; turret->life = -1; turret->timer = 0; turret->secret = 0; turret->health = 0.20; turret->hitship = NULL; turret->hitprojectile = turret_hitprojectile; if(type==2) turret->animate = mturret_animate; else turret->animate = turret_animate; turret->destroy = turret_explode; turret->turn = 0.05; /* Find a good starting angle */ if(type<2) for(a=0;a<2*M_PI;a++) if(!is_solid(x+cos(a)*5,y-sin(a)*5)) {turret->angle = a; break;} return turret; }
void Editor::load_layers() { layerselect.selected_tilemap = NULL; layerselect.layers.clear(); bool tsel = false; for(auto& i : currentsector->gameobjects) { auto go = i.get(); auto mo = dynamic_cast<MovingObject*>(go); if ( !mo && go->do_save() ) { layerselect.add_layer(go); auto tm = dynamic_cast<TileMap*>(go); if (tm) { if ( !tm->is_solid() || tsel ) { tm->editor_active = false; } else { layerselect.selected_tilemap = tm; tm->editor_active = true; tsel = true; } } } } layerselect.sort_layers(); layerselect.refresh_sector_text(); }
static void explosive_merge(ClientRegion *rgn, SpanVector const& me, SpanVector const& neighbor, MeshAccumulator *ma, int x, int y, int face) { uint8_t me_type[MAX_Z_DEPTH]; uint8_t neighbor_type[MAX_Z_DEPTH]; uint8_t me_flags[MAX_Z_DEPTH]; int me_z = 0; for (SpanVector::const_iterator i=me.begin(); i!=me.end(); ++i) { memset(&me_flags[me_z], i->flags, i->height); if (is_space(i->type)) { memset(&me_type[me_z], 0, i->height); } else { memset(&me_type[me_z], i->type, i->height); } me_z += i->height; } int neighbor_z = 0; for (SpanVector::const_iterator i=neighbor.begin(); i!=neighbor.end(); ++i) { if (is_solid(i->type)) { memset(&neighbor_type[neighbor_z], 1, i->height); } else { memset(&neighbor_type[neighbor_z], 0, i->height); } neighbor_z += i->height; } if (me_z > neighbor_z) { memset(&neighbor_type[neighbor_z], 0, me_z - neighbor_z); } int i=0; Slab s; s.x = x; s.y = y; while (i < me_z) { if (me_type[i] && !neighbor_type[i]) { int i0 = i; s.type = me_type[i]; s.flags = me_flags[i]; while ((i < me_z) && (me_type[i] == s.type) && (me_flags[i] == s.flags) && !neighbor_type[i]) { i++; } s.z0 = i0 + rgn->basement; s.z1 = i + rgn->basement; ma->setup(&s); ma->face(face); } else { i++; } } }
/* Shoot */ static int critter_shoot(struct Critter *critter, double angle) { double x = critter->physics.x + cos(angle)* critter->physics.radius; double y = critter->physics.y + sin(angle)* critter->physics.radius; if(is_solid(Round(x),Round(y))) return 0; Vector mvel = {cos(angle) * 10, sin(angle)*10}; add_projectile(make_bullet(x,y,addVectors(critter->physics.vel,mvel))); return 1; };
btCompoundShape * VoxelFile::get_shape() { if (shape != NULL) return shape; btCompoundShape * shape = new btCompoundShape(true); const float s = 0.5f; static btBoxShape * box_shape = new btBoxShape(btVector3(s, s, s)); btTransform transform; for (int x = 0; x < x_size; x++) for (int y = 0; y < y_size; y++) for (int z = 0; z < z_size; z++) { if (!is_solid(x, y, z)) continue; // ignore if not an exposed block if (is_solid(x + 1, y, z) && is_solid(x - 1, y, z) && is_solid(x, y + 1, z) && is_solid(x, y - 1, z) && is_solid(x, y, z + 1) && is_solid(x, y, z - 1)) continue; transform.setIdentity(); transform.setOrigin(btVector3(x + x_offset + 0.5f, y + y_offset + 0.5f, z + z_offset + 0.5f)); shape->addChildShape(transform, box_shape); } this->shape = shape; return shape; }
/* Check if there is any solid terrain inside a rectangle */ static int hitsolid_rect (int x, int y, int w, int h) { int x2 = x+w, y2 = y+h; for (; x < x2; x++) { for (; y < y2; y++) { if (is_solid(x,y)) return 1; } y-=h; } return 0; }
/* Turret animation */ static void turret_animate(struct SpecialObj *turret) { double dist; float targx=-1,targy=-1; int targplr; /* Get a target */ targplr = find_nearest_enemy(turret->x,turret->y,turret->owner, &dist); if(dist<160.0) { targx = players[targplr].ship->physics.x; targy = players[targplr].ship->physics.y; } else { targplr = find_nearest_pilot(turret->x,turret->y,turret->owner, &dist); if(dist<160.0) { targx = players[targplr].pilot.walker.physics.x; targy = players[targplr].pilot.walker.physics.y; } } /* Aim at target if found */ if(targx>=0) { double a = atan2(turret->y-targy, targx-turret->x); double d; if(a<0) a = 2*M_PI + a; d = shortestRotation(turret->angle,a); if(d<-0.2) { turret->turn = -0.2; } else if(d>0.2) { turret->turn = 0.2; } else { turret->turn = d/2; if(turret->timer==0) turret_shoot(turret); } } else { /* Restore normal turning speed */ if(turret->turn<0) turret->turn=-0.05; else turret->turn=0.05; } /* Rotate turret */ turret->angle += turret->turn; if(is_solid(turret->x+cos(turret->angle)*5,turret->y-sin(turret->angle)*5)) { turret->angle -= turret->turn; turret->turn = -turret->turn; } if(turret->angle>2*M_PI) turret->angle=0; else if(turret->angle<0) turret->angle=2*M_PI; turret->frame = Round(turret->angle/(2*M_PI)*(turret->frames-1)); }
/* If ground!=0, only y+ axis is searched */ static int find_turret_xy (int *tx, int *ty,int ground) { int x[4]={*tx,*tx,*tx,*tx}, y[4]={*ty,*ty,*ty,*ty}; int dx[4]={0,1,0,-1}, dy[4]={1,0,-1,0}; int r,loops=0; while(++loops<400) { for(r=0;r<4;r++) { if((ground&&r!=0) || is_water(x[r],y[r])) continue; x[r] += dx[r]; y[r] += dy[r]; if(is_solid(x[r],y[r])) { *tx = x[r]; *ty = y[r]; return 1; } } } return 0; }
/* Pixel perfect collision detection. */ int hit_solid_line (int startx, int starty, int endx, int endy, int *newx, int *newy) { int dx, dy, ax, ay, sx, sy, x, y, d; if (startx<0 || endx < 0 || startx >= lev_level.width || endx >= lev_level.width) { *newx = endx<0?0:endx>=lev_level.width?lev_level.width-1:endx; *newy = endy<0?0:endy>=lev_level.height?lev_level.height-1:endy; return TER_INDESTRUCT; } if (startx<0 || endy < 0 || startx >= lev_level.width || endy >= lev_level.height) { *newx = endx<0?0:endx>=lev_level.width?lev_level.width-1:endx; *newy = endy<0?0:endy>=lev_level.height?lev_level.height-1:endy; return TER_INDESTRUCT; } dx = endx - startx; dy = endy - starty; ax = abs (dx) << 1; ay = abs (dy) << 1; sx = (dx >= 0) ? 1 : -1; sy = (dy >= 0) ? 1 : -1; x = startx; y = starty; if (ax > ay) { d = ay - (ax >> 1); while (x != endx) { if (is_solid (x, y)) { *newx = x; *newy = y; return lev_level.solid[x][y]; } if (d > 0 || (d == 0 && sx == 1)) { y += sy; d -= ax; } x += sx; d += ay; } } else {
inline unsigned char get_safe(int x, int y, int z) { if (!is_solid(x, y, z)) return VOXEL_AIR; return get(x, y, z); }
inline bool is_surface(int x, int y, int z) { return !(is_solid(x - 1, y, z) && is_solid(x + 1, y, z) && is_solid(x, y - 1, z) && is_solid(x, y + 1, z) && is_solid(x, y, z - 1) && is_solid(x, y, z + 1)); }
void uxa_glyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst, PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs) { ScreenPtr screen = pDst->pDrawable->pScreen; uxa_screen_t *uxa_screen = uxa_get_screen(screen); if (uxa_screen->info->flags & UXA_USE_GLAMOR) { int ok; uxa_picture_prepare_access(pDst, UXA_GLAMOR_ACCESS_RW); uxa_picture_prepare_access(pSrc, UXA_GLAMOR_ACCESS_RO); ok = glamor_glyphs_nf(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs); uxa_picture_finish_access(pSrc, UXA_GLAMOR_ACCESS_RO); uxa_picture_finish_access(pDst, UXA_GLAMOR_ACCESS_RW); if (!ok) goto fallback; return; } if (!uxa_screen->info->prepare_composite || uxa_screen->force_fallback || !uxa_drawable_is_offscreen(pDst->pDrawable) || pDst->alphaMap || pSrc->alphaMap || /* XXX we fail to handle (rare) non-solid sources correctly. */ !is_solid(pSrc)) { fallback: uxa_check_glyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs); return; } /* basic sanity check */ if (uxa_screen->info->check_composite && !uxa_screen->info->check_composite(op, pSrc, NULL, pDst, 0, 0)) { goto fallback; } ValidatePicture(pSrc); ValidatePicture(pDst); if (!maskFormat) { /* If we don't have a mask format but all the glyphs have the same format, * require ComponentAlpha and don't intersect, use the glyph format as mask * format for the full benefits of the glyph cache. */ if (NeedsComponent(list[0].format->format)) { Bool sameFormat = TRUE; int i; maskFormat = list[0].format; for (i = 0; i < nlist; i++) { if (maskFormat->format != list[i].format->format) { sameFormat = FALSE; break; } } if (!sameFormat || uxa_glyphs_intersect(nlist, list, glyphs)) maskFormat = NULL; } } if (!maskFormat) { if (uxa_glyphs_to_dst(op, pSrc, pDst, xSrc, ySrc, nlist, list, glyphs)) goto fallback; } else { if (uxa_glyphs_via_mask(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs)) goto fallback; } }
pathfinding::directed_graph_ptr logical_world::create_directed_graph(bool allow_diagonals) const { profile::manager pman("logical_world::create_directed_graph"); std::vector<variant> vertex_list; std::map<std::pair<int,int>, int> vlist; for(auto p : heightmap_) { int x = p.first.first; int y = p.second; int z = p.first.second; if(y < size_y() - 1) { if(is_solid(x, y+1, z) == false) { vertex_list.push_back(variant_list_from_position(x,y+1,z)); vlist[std::make_pair(x,z)] = y+1; } } else { vertex_list.push_back(variant_list_from_position(x,y+1,z)); vlist[std::make_pair(x,z)] = y+1; } } pathfinding::graph_edge_list edges; for(auto p : vertex_list) { const int x = p[0].as_int(); const int y = p[1].as_int(); const int z = p[2].as_int(); std::vector<variant> current_edges; auto it = vlist.find(std::make_pair(x+1,z)); if(it != vlist.end() && !is_xedge(x+1) && !is_solid(x+1,it->second,z)) { current_edges.push_back(variant_list_from_position(x+1,it->second,z)); } it = vlist.find(std::make_pair(x-1,z)); if(it != vlist.end() && !is_xedge(x-1) && !is_solid(x-1,it->second,z)) { current_edges.push_back(variant_list_from_position(x-1,it->second,z)); } it = vlist.find(std::make_pair(x,z+1)); if(it != vlist.end() && !is_zedge(z+1) && !is_solid(x,it->second,z+1)) { current_edges.push_back(variant_list_from_position(x,it->second,z+1)); } it = vlist.find(std::make_pair(x,z-1)); if(it != vlist.end() && !is_zedge(z-1) && !is_solid(x,it->second,z-1)) { current_edges.push_back(variant_list_from_position(x,it->second,z-1)); } if(allow_diagonals) { it = vlist.find(std::make_pair(x+1,z+1)); if(it != vlist.end() && !is_xedge(x+1) && !is_zedge(z+1) && !is_solid(x+1,it->second,z+1)) { current_edges.push_back(variant_list_from_position(x+1,it->second,z+1)); } it = vlist.find(std::make_pair(x+1,z-1)); if(it != vlist.end() && !is_xedge(x+1) && !is_zedge(z-1) && !is_solid(x+1,it->second,z-1)) { current_edges.push_back(variant_list_from_position(x+1,it->second,z-1)); } it = vlist.find(std::make_pair(x-1,z+1)); if(it != vlist.end() && !is_xedge(x-1) && !is_zedge(z+1) && !is_solid(x-1,it->second,z+1)) { current_edges.push_back(variant_list_from_position(x-1,it->second,z+1)); } it = vlist.find(std::make_pair(x-1,z-1)); if(it != vlist.end() && !is_xedge(x-1) && !is_zedge(z-1) && !is_solid(x-1,it->second,z-1)) { current_edges.push_back(variant_list_from_position(x-1,it->second,z-1)); } } edges[variant_list_from_position(x, y, z)] = current_edges; } return pathfinding::directed_graph_ptr(new pathfinding::directed_graph(&vertex_list, &edges)); }
void Emitter::update(Player& owner) { float t = timer.GetElapsedTime(); float dt = t - lastUpdate; if (dt < 1.0 / 100.0) return; // printf("dt = %f\n", dt); lastUpdate = t; // Delete expired particles while (!particles.empty()) { const Particle& p = particles.front(); if (t - p.birthday > p.lifetime || p.dead) particles.pop_front(); else break; } // TODO: Use something nicer than an AABB for this std::vector<int> playerIDs; std::vector<AABB> playerBoundingAreas; const int playerRadius = 32; for (auto& kvpair : GAME.world.players) { if (kvpair.second.identifier == owner.identifier) continue; // Ignore collisions with the player since they happen all the time playerBoundingAreas.push_back(AABB(kvpair.second.position.x - playerRadius, kvpair.second.position.y - playerRadius, playerRadius * 2, playerRadius * 2)); playerIDs.push_back(kvpair.second.identifier); } // Update particles for (Particle& p : particles) { if (p.dead) continue; Vec2<float> v = p.acceleration * dt + p.velocity; Vec2<float> r = p.position + (v + p.velocity) * 0.5 * dt; p.velocity = v; p.position = r; p.age = t - p.birthday; // Check for collisions Tile tile = worldTileAtPixel(p.position.x, p.position.y); // printf("tile at (%d, %d) -> %d -> is solid %d\n", (int)p.position.x, (int)p.position.y, (int)tile, is_solid(tile)); // printf(" yes it really is %u\n", (unsigned)tile); // printf(" %u %u %u %u %u %u %u %u %u\n", (unsigned)Tile::Black, (unsigned)Tile::Dirt, (unsigned)Tile::Grass, (unsigned)Tile::Tarmac, (unsigned)Tile::Pavement, (unsigned)Tile::RoadCenterLine, (unsigned)Tile::BrickWall, (unsigned)Tile::DoorClosedN, (unsigned)Tile::LAST); if (is_solid(tile)) p.dead = true; for (int i = 0, playerCount = playerBoundingAreas.size(); i < playerCount; i++) { // TODO: Work out the direction from the given player int dimension = 0; // owner.z if (collides(playerBoundingAreas[i], p.position.x, p.position.y, dimension)) { // Kill the particle p.dead = true; // Damage the player playerDamaged(owner.identifier, playerIDs[i], 1); } } // Player collisions } // Spawn new particles int n = 0; if (particleClock.GetElapsedTime() + lastSpawned > 1.0 / spawnFrequency) { lastSpawned += particleClock.GetElapsedTime(); particleClock.Reset(); while (lastSpawned >= 1.0 / spawnFrequency) { n++; lastSpawned -= 1.0 / spawnFrequency; } } if (n == 0) return; for (int i = 0; i < n; i++) { Particle p(t, 1.0, Vec2<float>(position.x, position.y)); float theta = normalRealInRange(rng, direction.angle - arc.angle / 2.0, direction.angle + arc.angle / 2.0, 2.0); float speed = normalRealInRange(rng, averageSpeed / 2.0, averageSpeed * 3.0 / 2.0, 2.0); // printf("Random test: %f\n", normalRealInRange(rng, 10.0, 20.0, 2.0)); // printf("Theta angle: %f | %f => %f\n", direction.angle, arc.angle, theta); // printf("Speed: %f => %f\n", averageSpeed, speed); p.velocity = Vec2<float>::FromPolar(speed, Angle(theta)); // float theta2 = normalRealInRange(rng, 2.0 * theta - direction.angle, direction.angle, 2.0); // float accel = normalRealInRange(rng, 2.0 * theta - direction.angle, direction.angle, 2.0); p.acceleration = Vec2<float>(0.0, 0.0); //Vec2<float>::FromPolar(- speed, Angle(theta2)); particles.push_back(p); } }