Changeset 346
- Timestamp:
- 05/30/08 08:24:53 (6 months ago)
- Files:
-
- trunk/qd/dt.d (modified) (21 diffs)
- trunk/qd/qd.d (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/qd/dt.d
r345 r346 8 8 import qd, dglut.vector; 9 9 10 import tools.time; 11 bool delegate() blink(float _delay) { 12 return stuple(_delay, true, sec()) /apply/ (float delay, ref bool state, ref float last) { 13 if (sec() < last) { 14 last = sec(); // timer wrapped around. Can't help this. Don't switch. Hope the user doesn't notice. 15 return state; 16 } 17 while (sec() - last > delay) { last += delay; state = !state; } 18 return state; 19 }; 20 } 21 10 22 float randf() { return (cast(float)rand())/(cast(float)(typeof(rand()).max)); } 11 23 … … 16 28 abstract void draw(); 17 29 abstract void update(); 30 } 31 32 interface InteractingThing { 33 void select(); void unselect(); 34 void highlight(); void unhighlight(); 35 bool isSelected(); bool isHighlighted(); 36 } 37 38 template InteractingImpl() { 39 bool selected, highlighted; 40 void select() { selected = true; highlighted = true; } 41 void highlight() { highlighted = true; } 42 void unselect() { selected = false; } void unhighlight() { highlighted = false; } 43 bool isSelected() { return selected; } bool isHighlighted() { return selected || highlighted; } 18 44 } 19 45 … … 28 54 class LivingThing : WorldThing { 29 55 private { 30 int life, age;56 int life, maxlife, age; 31 57 void delegate(LivingThing) onDeath; 32 58 } … … 34 60 void damage(int howmuch) { life-=howmuch; if (life!>0) onDeath(this); } 35 61 void die() { damage(life); onDeath(this); } 36 mixin This!("onDeath, super(pos, radius), life=10 ");62 mixin This!("onDeath, super(pos, radius), life=10; #maxlife=life; "); 37 63 } 38 64 … … 108 134 109 135 class Critter : LivingThing , MovingThing { 110 //void draw() { circle(x, y, radius, Black, Fill=Blue~White~White); }111 136 void draw() { 112 137 bufferedCircle(pos.to!(int).tuple, radius, Black, Fill=Blue~White~White); … … 122 147 void damage(typeof(life) d) { 123 148 super.damage(d); 124 if (life!>0) addEffect!(RingEffect)(Blue~White~White, pos, 10, 15); 149 if (life!>0) { 150 addEffect!(RingEffect)(White~Yellow, pos, 10, 15); 151 addEffect!(RingEffect)(Black, pos, 11, 15); 152 } 125 153 } 126 154 void update() { … … 130 158 float speed; 131 159 void delegate() win; 160 void done() { win(); die(); } 132 161 private { 133 int maxlife;134 162 Path path; 135 163 Path.Train train; 136 164 void initTrain() { 137 train=path.new Train(pos, speed, win);165 train=path.new Train(pos, speed, &done); 138 166 } 139 167 long id; 140 168 } 141 mixin This!("path, speed, win, id, super(onDeath, pos, radius=20, life=20), # maxlife=life; #initTrain; ");169 mixin This!("path, speed, win, id, super(onDeath, pos, radius=20, life=20), #initTrain; "); 142 170 } 143 171 … … 280 308 } 281 309 282 class Turret : WorldThing { 310 class Turret : WorldThing, InteractingThing { 311 mixin InteractingImpl!(); 283 312 struct Settings { 284 313 int range, rate; … … 296 325 void draw() { 297 326 auto ipos = pos.to!(int); 298 if ( mouseOver(this)) {327 if (isHighlighted) { 299 328 circle(ipos.tuple, settings.range+1, White); 300 329 circle(ipos.tuple, settings.range, Black); 301 330 circle(ipos.tuple, settings.range-1, White); 302 331 } 303 bufferedCircle(ipos.tuple, radius, Black, Fill=White~Green); 332 if (isSelected) bufferedCircle(ipos.tuple, radius, Black, Fill=White~Green~(Blue~White)); 333 else bufferedCircle(ipos.tuple, radius, Black, Fill=White~Green); 304 334 Teh_Ordnance.draw; 305 335 } … … 342 372 bool break_mode; 343 373 Path path; 374 int score; 375 void delegate() critter_hit; 344 376 } 345 377 TargetGroup critters; 346 mixin This!("rate, groupsize, breaktime, life, path, super(pos, radius=15), #counter=0;378 mixin This!("rate, groupsize, breaktime, life, critter_hit, path, super(pos, radius=15), #counter=0; 347 379 #group_left=groupsize; #critters=new TargetGroup; #break_mode=true; #break_left=breaktime; "); 348 380 void draw() { … … 354 386 else if (group_left) text = Format(group_left); 355 387 critters.draw; 356 withSet(alpha, 64, { circle(pos.to!(int).tuple, radius, White, Fill=Background~Black); }); 388 withSet(alpha, 64, { 389 circle(pos.to!(int).tuple, radius, Fill=Background~Black); 390 }); 357 391 .print(pos.to!(int).tuple, Center, Black, text); 358 392 } 359 void win() { throw new Exception("The critters win!"); }393 void win() { critter_hit(); } 360 394 static long id=0; 361 395 void update() { … … 378 412 } else group_left --; 379 413 // yes the last critter is intentionally stronger. 380 auto newCritter=new Critter(path, 0.6, &win, id++, &critters.removeAs!(LivingThing), pos, 10, cast(int) life); 414 auto newCritter=new Critter(path, 0.5, &win, id++, 415 stuple(critters, this) /apply/ (TargetGroup tg, typeof(this) This, LivingThing lt) { tg.remove(cast(Critter) lt); This.score += lt.maxlife; }, 416 pos, 10, cast(int) life); 381 417 critters.addThing(newCritter); newCritter.update; 382 418 } … … 441 477 } 442 478 443 bool delegate(WorldThing) mouseOver; 479 class InteractionSet { 480 alias InteractingThing IT; 481 bool[IT] selected, highlighted; 482 void cleanHighlights() { foreach (entry; highlighted.keys) entry.unhighlight; highlighted = null; } 483 void cleanSelection() { foreach (entry; selected.keys) entry.unselect; selected = null; } 484 void rmHighlight(IT it) { it.unhighlight; highlighted.remove(it); } 485 void addHighlight(IT it) { highlighted[it] = true; it.highlight; } 486 void mouse_up() { 487 if (!(SDLKey.LCtrl in keystate)) cleanSelection; 488 foreach (entry; highlighted.keys) { 489 entry.select; 490 selected[entry] = true; 491 } 492 cleanHighlights(); 493 } 494 } 444 495 445 496 import test13, tools.functional; 446 497 void main() { 498 auto blink_fn = blink(0.5); 447 499 vec2f mouse_pos, start; 448 500 bool drag=false; 449 501 bool[int] pressed; 450 WorldThing[] select; 451 auto moveMouseOver=(WorldThing w) { 452 foreach (s; select) if (w is s) return true; 453 with (w) return ((pos - mouse_pos).length()<=radius); 454 }; 455 auto dragMouseOver=(WorldThing wt) { 456 if (SDLKey.LCtrl in pressed) foreach (s; select) if (wt is s) return true; 502 auto thingies = new InteractionSet; 503 bool underMouse(WorldThing wt) { 504 with (wt) return (pos - mouse_pos).length() <= radius; 505 } 506 bool underSelection(WorldThing wt) { 507 logln(cast(void*) wt, " under selection?"); 457 508 with (wt) { 458 509 if (pos.x+radius<min(start.x, mouse_pos.x)) return false; … … 461 512 if (pos.y-radius>max(start.y, mouse_pos.y)) return false; 462 513 } 514 logln(cast(void*) wt, " under selection."); 463 515 return true; 464 }; 465 mouseOver=moveMouseOver; 516 } 466 517 screen(640, 480); 467 518 while (!mouse.clicked) { flip; events; } … … 469 520 Group!(Thing) group; 470 521 auto path=new Path(false, 471 vec2f(30, 30), vec2f(300, 30), vec2f(300, 300), vec2f(30, 300), vec2f(30, 90) 522 vec2f(60, 60), vec2f(60, 300), vec2f(200, 300), vec2f(200, 30), 523 vec2f(440, 30), vec2f(440, 150), vec2f(300, 150), vec2f(300, 300), vec2f(500, 300) 472 524 ); 473 525 474 526 auto bg_surf = screen.With(screen.w, screen.h) = { 475 527 FatLine fl; 476 fl = new FatLine( vec2f(300, 400) ~path.points, (float d) {528 fl = new FatLine(path.points, (float d) { 477 529 if (abs(d) > fl.width) return Background; 478 530 else if (abs(d) > fl.width - 2) return Background.blend(Black, (fl.width - abs(d)) / 2f); … … 483 535 }; 484 536 485 auto spawner=new SpawnPoint(/* rate */ 48, /* groupsize */ 10, /* breaktime */ 5, /* start life */ 64, path, vec2f(300, 400)); 537 int hits_counter = 10; 538 void hit() { 539 hits_counter --; 540 if (!hits_counter) throw new Exception("You lose!"); 541 } 542 auto spawner=new SpawnPoint(/* rate */ 48, /* groupsize */ 10, /* breaktime */ 5, /* start life */ 64, &hit, path, path.points[0]); 486 543 group=new typeof(group)([cast(Thing)spawner]); 487 544 group.addThing(new Turret( 488 545 Turret.Settings(115, 24, false), 489 546 Ammo.Settings(/*speed*/ 1.5f, /*aim*/ 0.25, /*momentum_speed*/0, /*momentum_dir*/ 1, /*damage*/ 8, /*lifetime*/256, /*linger*/true, /*punchthrough*/false), 490 spawner.critters, vec2f( 85, 220)547 spawner.critters, vec2f(30, 340) 491 548 )); 492 549 group.addThing(new Turret( 493 Turret.Settings(115, 6, true),550 Turret.Settings(115, 12, false), 494 551 Ammo.Settings(/*speed*/ 0.9f, /*aim*/ 0, /*momentum_speed*/0.9, /*momentum_dir*/ 0.98, /*damage*/ 2, /*lifetime*/1024, true, false, true), 495 spawner.critters, vec2f( 185, 135)552 spawner.critters, vec2f(360, 85) 496 553 )); 497 554 group.addThing(effects); … … 502 559 scope(exit) writefln("Average FPS: ", avg/(cast(float)count)); 503 560 auto limiter=new FrameLimiter(60, 60); 561 bool delegate(WorldThing) shouldHighlight = &underMouse;; 504 562 do with (group) { 505 563 update; … … 507 565 display.blit(bg_surf); 508 566 prettyprint(0, 0, Bottom|Right, 509 "Test .. [size -1]test![/size] [b]Bold, [i]italic and [u]underlined![/u][/i][/b] [i]Just italic now.[/i] [b][color #f00]Red?[/color][/b]Done!");567 Format("Score: [b][size -2]", spawner.score, "[/size][/b]")); 510 568 draw; 569 withSet(alpha, 64, { circle(path.points[$-1].to!(int).tuple, 15, Fill=Yellow~Black); }); 570 string formatting = Format(hits_counter); 571 auto b = blink_fn(); 572 if (hits_counter <= 3) formatting = "[size +4]"~(b?"[color #f88][b]":"")~formatting~(b?"[/b][/color]":"")~"[/size]"; 573 formatting = "[color #c80]"~formatting~"[/color]"; 574 .prettyprint(path.points[$-1].to!(int).tuple, Center, formatting); 511 575 if (drag) { 512 576 tintfill(start.min(mouse_pos).to!(int).tuple, start.max(mouse_pos).to!(int).tuple, Blue~White); … … 520 584 if (key==27) throw new Error("Quit"); 521 585 }, (int x, int y, ubyte button, int p) { 586 foreach (thing; group) { 587 auto wt = cast(WorldThing) thing, it = cast(InteractingThing) thing; 588 if (wt && it) 589 if (shouldHighlight(wt)) thingies.addHighlight(it); 590 else thingies.rmHighlight(it); 591 } 522 592 if (!button) { 523 593 mouse_pos.x=x; mouse_pos.y=y; … … 525 595 if (p==1) { 526 596 start.x=x; start.y=y; 527 mouseOver=dragMouseOver;528 597 drag=true; 598 shouldHighlight = &underSelection; 529 599 } 530 600 if (p==-1) { 531 if (!(SDLKey.LCtrl in pressed)) select=null; 532 foreach (critter; group) if (auto wt=cast(WorldThing) critter) if (mouseOver(wt)) select~=wt; 533 mouseOver=moveMouseOver; 601 thingies.mouse_up; 602 shouldHighlight = &underMouse; 534 603 drag=false; 535 604 } … … 546 615 fps=0; 547 616 } 548 // with (Background) SDL_FillRect(display.surface, null, SDL_MapRGBA(display.surface.format, values[0], values[1], values[2], 0));549 617 } while (true); 550 618 } trunk/qd/qd.d
r345 r346 441 441 const string yx=(first?"y":"x"); 442 442 const string str=" 443 auto x="~(first?" xradius":"0")~";444 auto y="~(first?"0":" yradius")~";445 auto xchange= yradius*yradius*"~(first?"(1-2*xradius)":"1")~";446 auto ychange= xradius*xradius*"~(first?"1":"(1-2*yradius)")~";443 auto x="~(first?"radius":"0")~"; 444 auto y="~(first?"0":"radius")~"; 445 auto xchange=radius*radius*"~(first?"(1-2*radius)":"1")~"; 446 auto ychange=radius*radius*"~(first?"1":"(1-2*radius)")~"; 447 447 auto error=0; 448 auto stopx="~(first?"y2square* xradius":"0")~";449 auto stopy="~(first?"0":"x2square* yradius")~";448 auto stopx="~(first?"y2square*radius":"0")~"; 449 auto stopy="~(first?"0":"x2square*radius")~"; 450 450 while (stopx"~(first?">=":"<=")~"stopy) { 451 451 putpixel(cx+x, cy+y, col); … … 486 486 void circle(T...)(T t) { 487 487 static assert(T.length!<3, "Circle: Needs x, y and radius"); 488 int cx=cast(int)t[0], cy=cast(int)t[1], xradius=cast(int)t[2];488 int cx=cast(int)t[0], cy=cast(int)t[1], radius=cast(int)t[2]; 489 489 SDL_LockSurface(display.surface); 490 490 scope(exit) { SDL_UnlockSurface(display.surface); if (doFlip) flip; } 491 491 execParams(t[3..$]); 492 auto yradius=xradius; 493 if (xradius!>0) return; 492 if (radius!>0) return; 494 493 static if (T.length>3 && is(T[3]: int)) yradius=t[3]; 495 494 static if (Select!(back_rgb, T) != -1) { 496 auto ratio=xradius*1f/yradius;497 495 auto back_sdl=SDL_MapRGBA(display.surface.format, back.values[0], back.values[1], back.values[2], 0); 498 for (int i=0; i<= yradius; ++i) {499 ushort j=cast(ushort)(sqrt(cast(real)( yradius*yradius-i*i))*ratio);496 for (int i=0; i<=radius; ++i) { 497 ushort j=cast(ushort)(sqrt(cast(real)(radius*radius-i*i))); 500 498 hline(cx-j, cy+i, 2*j, back_sdl); 501 hline(cx-j, cy-i, 2*j, back_sdl); 502 } 503 } 504 auto x2square=2*xradius*xradius; 505 auto y2square=2*yradius*yradius; 506 uint col=SDL_MapRGBA(display.surface.format, color.values[0], color.values[1], color.values[2], 0); 507 { mixin(circle_bresenham_pass!(true).str); } 508 { mixin(circle_bresenham_pass!(false).str); } 499 if (i) hline(cx-j, cy-i, 2*j, back_sdl); 500 } 501 } 502 static if (Select!(back_rgb, T) == -1 || Select!(rgb, T) != -1) { 503 auto x2square=2*radius*radius, y2square=x2square; 504 uint col=SDL_MapRGBA(display.surface.format, color.values[0], color.values[1], color.values[2], 0); 505 { mixin(circle_bresenham_pass!(true).str); } 506 { mixin(circle_bresenham_pass!(false).str); } 507 } 509 508 } 510 509 … … 622 621 } 623 622 623 bool[int] keystate; 624 624 625 /// parameters to key: which key, and if it's pressed or released 625 626 /// parameters to mouse: x, y, button [Left: 1, Mid: 2, Right: 3], change [1: pressed, -1: released] … … 629 630 switch (evt.type) { 630 631 case SDL_EventType.MouseMotion: 631 with (evt.motion) if (mouse) mouse(x, y, 0, 0); else updateMouse(x, y, 0, 0); 632 with (evt.motion) { 633 updateMouse(x, y, 0, 0); 634 if (mouse) mouse(x, y, 0, 0); 635 } 632 636 break; 633 637 case SDL_EventType.MouseButtonDown: 634 with (evt.button) if (mouse) mouse(x, y, button, 1); else updateMouse(x, y, button, 1); 638 with (evt.button) { 639 updateMouse(x, y, button, 1); 640 if (mouse) mouse(x, y, button, 1); 641 } 635 642 break; 636 643 case SDL_EventType.MouseButtonUp: 637 with (evt.button) if (mouse) mouse(x, y, button, -1); else updateMouse(x, y, button, -1); 644 with (evt.button) { 645 updateMouse(x, y, button, -1); 646 if (mouse) mouse(x, y, button, -1); 647 } 638 648 break; 639 649 case SDL_EventType.KeyDown: 650 keystate[evt.key.keysym.sym] = true; 640 651 if (key) key(evt.key.keysym.sym, true); 652 break; 641 653 case SDL_EventType.KeyUp: 654 keystate.remove(evt.key.keysym.sym); 642 655 if (key) key(evt.key.keysym.sym, false); 643 656 break;
