@Override public void update(View v) { long newtime = System.nanoTime(); // �ɋ}������ // �[������ if (lastSeedCount != fruitsSplatted.size()) { Random random = new Random(); int randomIndex = random.nextInt(2) + 1; if (randomIndex % 2 == 0) { // ����������+0.5�͈͂ł����Ă��� // 1~5�͈̔͂��쐬����1/10�ɂ��� randomSpeed += (random.nextInt(3) + 1) / 10.0f; float decimalSpeed = random.nextFloat(); // 0.1~1.0 // randomSpeed = random.nextInt(4) + decimalSpeed + 1; // 1~5 System.out.println(randomSpeed); } lastSeedCount = fruitsSplatted.size(); // �ʕ��̕\���� } String speedStr = String.format("SPEED:%f", randomSpeed); System.out.println(speedStr); float elapsedsecs = (float) (newtime - frtime) / ONESEC_NANOS * randomSpeed; frtime = newtime; fps = (int) (1 / elapsedsecs); // update combo hits Iterator<Combo> hcit = hitCombos.keySet().iterator(); while (hcit.hasNext()) { Combo combo = hcit.next(); ComboHit ch = hitCombos.get(combo); ch.y -= COMBOHIT_SPEED * elapsedsecs; float chtime = frtime - ch.hitTime; ch.alpha = (int) (255 * (1.0f - chtime / COMBOHIT_DISPLAYTIME)); if (frtime - ch.hitTime > COMBOHIT_DISPLAYTIME / 3) fps = 0; // excuse to put a breakpoint here if (frtime - ch.hitTime > COMBOHIT_DISPLAYTIME) hcit.remove(); } if (gamestate == State.STARTROUND) { // this goofy construction is to make sure we initialize the round from // the update/draw thread, not from the UI thread. initRound(); return; } if (width == 0) { // set variables that rely on screen size width = v.getWidth(); height = v.getHeight(); wallxcenter = width / 2; wallycenter = (int) (height * WALL_Y_CENTER_FACTOR); inity = (int) (INIT_SELECTABLE_Y_FACTOR * height); // initial fruit placement, also bottom of wall. // attempt to compute wall bounds at wall z from screen size. constants are pure // magic, found thru trial and error iterations. // if the background picture changes, they will need to be recalibrated. wallbounds_at_wall_z.set( (int) (-1.5 * width), (int) (-height * .94), (int) (2.43 * width), inity); // wall bounds AT WALL Z (!!WaLLzeY!!) // magic trial and error world-bounds contants, based on screen image size minXbound = 8 * -width; maxXbound = 8 * width; maxYbound = 5 * height; // compute wall bounds at screen z, used for clipping. int effl = (int) (wallbounds_at_wall_z.left + (WALLZFACT * (wallxcenter - wallbounds_at_wall_z.left))); int efft = (int) (wallbounds_at_wall_z.top + (WALLZFACT * (wallycenter - wallbounds_at_wall_z.top))); int effr = (int) (wallbounds_at_wall_z.right + (WALLZFACT * (wallxcenter - wallbounds_at_wall_z.right))); int effb = (int) (wallbounds_at_wall_z.bottom + (WALLZFACT * (wallycenter - wallbounds_at_wall_z.bottom))); wallbounds_at_screen_z.set(effl, efft, effr, effb); p.setTextSize(act.TS_NORMAL); p.setTypeface(act.getGameFont()); String t = "SCORE: 999999"; rhstextoffset = (int) p.measureText(t); p.getTextBounds(t, 0, t.length() - 1, scaledDst); statstextheight = (int) (scaledDst.height() + 5); statstextheight2 = statstextheight * 2; } if (gamestate == State.RUNNING && fruitsSelectable.size() < maxShownSelectableFruit && seedsQueued.size() > 0 && frtime > possspawntime + MIN_SPAWN_INTERVAL_NANOS) { possspawntime = frtime; // "every now and then" make a fruit available if (Math.random() > .6) { Fruit newf = null; if (fruitsRecycled.size() > 0) { // recycle a fruit if we can newf = fruitsRecycled.get(0); fruitsRecycled.remove(0); } else { // create if needed newf = new Fruit(); } // choose fruit Seed s = seedsQueued.get(0); seedsQueued.remove(0); int initx = (int) -s.halfWidth; int speed = selectable_speed; if (Math.random() > .5) { initx = (int) (width + s.halfWidth); speed = -speed; } newf.init(s, initx, inity, 0, speed); fruitsSelectable.add(newf); } } else if (gamestate == State.RUNNING && fruitsSelectable.size() == 0 && fruitsFlying.size() == 0 && seedsQueued.size() == 0) { // round is complete if (nWallSplats * 100 / nTotFruit >= minRoundPassPct) { act.playSound(Sound.PASSLEVEL); round++; gamestate = State.ROUNDSUMMARY; } else loseLife(); } // update fruit positions synchronized (fruitsFlying) { Iterator<Fruit> fit = fruitsFlying.iterator(); while (fit.hasNext()) { Fruit f = fit.next(); f.x += f.vx * elapsedsecs; f.y += f.vy * elapsedsecs; f.z += f.vz * elapsedsecs; f.vy += ACC_GRAVITY * elapsedsecs; if (f.z >= WALL_Z && wallbounds_at_wall_z.contains((int) f.x, (int) f.y)) { // fruit has hit wall fit.remove(); fruitsSplatted.add(f); nWallSplats++; if (f.isBonus == true) { score += f.seed.points * 5; } else { score += f.seed.points; } act.playSound(f.getSplatSound()); // check combo for (Combo c : combos) { neededSeeds.clear(); neededSeeds.addAll(c.seeds); neededSeeds.remove(f.seed); comboFruits.clear(); comboFruits.add(f); for (Fruit spf : fruitsSplatted) { if (neededSeeds.contains(spf.seed)) { if (spf.getBounds().intersect(f.getBounds())) { neededSeeds.remove(spf.seed); comboFruits.add(spf); } if (neededSeeds.size() == 0) break; } } if (neededSeeds.size() == 0) { // combo is hit score += c.points; for (Fruit spf : comboFruits) { fruitsSplatted.remove(spf); } // display combo hit message "somewhere next to" combo hit effpt = renderFromZ(f.x, f.y, f.z, wallxcenter, wallycenter); ComboHit ch = new ComboHit(); ch.x = effpt.x + (float) Math.random() * 100 - 50; ch.y = effpt.y + (float) Math.random() * 100 - 80; // play sound act.playSound(Sound.COMBO); // ensure combo display is fully onscreen p.getTextBounds(c.name, 0, c.name.length(), scaledDst); if (ch.x < 0) ch.x = 0; else if (ch.x > width - scaledDst.width()) ch.x = width - scaledDst.width(); ch.hitTime = System.nanoTime(); hitCombos.put(c, ch); } } } else if (f.y > inity && f.y < inity + f.vy * elapsedsecs && f.z > WALL_Z / 2) { // fruit has hit ground near wall fit.remove(); fruitsSplatted.add(f); } else if (f.z > WALL_Z // here we goofily force java to call render function when we need it && (effpt = renderFromZ(f.x, f.y, f.z, wallxcenter, wallycenter)) != null && wallbounds_at_screen_z.contains(effpt.x, effpt.y)) { // wild pitch, behind wall fit.remove(); fruitsRecycled.add(f); } else if (f.y > maxYbound || f.x >= maxXbound || f.x <= minXbound) { // wild pitch, out of bounds fit.remove(); fruitsRecycled.add(f); } } } if (gamestate == State.RUNNING) { synchronized (fruitsSelectable) { Iterator<Fruit> fit = fruitsSelectable.iterator(); while (fit.hasNext()) { Fruit f = fit.next(); if (f != selectedFruit) { // f.x += f.vx * elapsedsecs; f.x += f.vx * elapsedsecs * f.scroll; // wobble displayable fruit up and down, and return them to regular line when let go // int targy = inity + (int)(Math.sin(f.x/15)* selectable_y_play); // f.y += (targy - f.y) / SELECTABLE_FRUIT_BRAKING_FACTOR; int targy = inity + (int) (Math.sin(f.x / 65) * selectable_y_play); f.y += (targy - f.y) / SELECTABLE_FRUIT_BRAKING_FACTOR; } if (f.x < -f.seed.halfWidth || f.x > width + f.seed.halfWidth) { // we floated off screen fit.remove(); fruitsRecycled.add(f); } } } } }