文档章节

程序员表白程序,开放源码,不断更新

w
 wuxia2001
发布于 2014/12/17 17:12
字数 4111
阅读 379
收藏 0

这是我为自己写的一款表白的程序,几经努力把它完成为一个完整的程序,这是我准备完成的程序之爱系列第一辑,希望能多做几辑吧。

源码地址:https://github.com/wuxia2001/mylove.git

APK地址:http://zhushou.360.cn/detail/index/soft_id/1380324   

先上图吧

                            



一共三个主界面和一个设置界面,主界面都是用surfaceview画出来的。三个界面都是自己设计的,作为一个程序员,非美工,就不要对我的美术素养太苛刻了哈!

每个界面都有底层背景,加背景的方法:

//外面加背景 
l1.setBackgroundResource(R.drawable.q2);

//Surfaceview做设置
//透明
setZOrderOnTop(true);
holder.setFormat(PixelFormat.TRANSPARENT);

第一个界面,楚楚这两个字是用爱心一点点渐现出来的,在这里,画出字有两种方法,第一种,是我用awt得到的字的坐标,然后保存在文件里,再从文件里读出坐标,从而画出字。

生成坐标的代码如下,这部分代码只能在电脑上运行,不能移植到手机端,所以这种方法只能用来显示事先设计好的字,但这种方法写出来的字效果去很好。代码如下

/**
	 * 要写的字,我这里只试过单字,要保存的文件名,字体,调整X和Y位置,宽和高
	 * @param zi
	 * @param filename
	 * @param font
	 * @param outx
	 * @param outy
	 * @param w
	 * @param h
	 */
	public static void zi(String zi, String filename, Font font,
			int outx,int outy,int w,int h){
		try
		{
			//张 黑体,30号字。w40 h 29 array_zhang
			//晚 黑体 30 
			//I 宋体 30号。 w12 h24 array_I
			//U 宋体 30 号粗 w17 h24 array_U
			//Font font = new Font("黑体", Font.PLAIN, 30);
			
			AffineTransform at = new AffineTransform();
			FontRenderContext frc = new FontRenderContext(at, true, true);
			GlyphVector gv = font.createGlyphVector(frc, zi); // 要显示的文字
			Shape shape = gv.getOutline(outx,outy);
			int weith = w;
			int height = h;
			boolean[][] view = new boolean[weith][height];
			for (int i = 0; i < weith; i++)
			{
				for (int j = 0; j < height; j++)
				{
					if (shape.contains(i, j))
					{
						view[i][j] = true;
					} else
					{
						view[i][j] = false;
					}
					//if(i == 7 && j>=3 && j<=6) view[i][j] = true;
					//if(i == 6 && j == 8) view[i][j] = true;
				}
			}
			for (int j = 0; j < height; j++)
			{
				for (int i = 0; i < weith; i++)
				{
					if (view[i][j])
					{
						System.out.print("@");// 替换成你喜欢的图案
					} else
					{
						System.out.print(" ");
					}
				}
				System.out.println();
			}
			
			File file = new File(filename);  //存放数组数据的文件			 
			  FileWriter out = new FileWriter(file);  //文件写入流			 
			  //将数组中的数据写入到文件中。每行各数据之间TAB间隔
			  for(int j=0;j<height;j++){
			   for(int i=0;i<weith;i++){
				   if(view[i][j])	
					   out.write(1+"b");
				   else out.write(0+"b");
			   }
			   out.write("n");
			  }
			  out.close();
		} catch (Exception e)
		{
			e.printStackTrace();
		}
	}


直接进行调用 zi("楚","array_chu.txt",font,-1,17,20,20);就可以得坐标。

在手机端读出来并写出来的代码如下:


// 花 type 1为花,2为爱心
	/**
	 * 开始x,开始Y坐标,字的宽,高,文件名字,放大倍数,type为图片种类
	 * @param stx
	 * @param sty
	 * @param w
	 * @param h
	 * @param filename
	 * @param beishu
	 * @param type
	 */
	public void show_I(int stx, int sty, int w, int h, String filename,
			int beishu, int type) {
		int startx = stx, starty = sty;
		try {
			int weith = w;
			int height = h;
			boolean[][] arr = new boolean[weith][height]; // 插入的数组
			String file = filename;
			InputStream ins = Util.init().getAssetsInputStream(mContext, file);
			BufferedReader in = new BufferedReader(new InputStreamReader(ins)); //
			String line; // 一行数据
			int row = 0;
			// 逐行读取,并将每个数组放入到数组中
			StringBuilder sb = new StringBuilder();
			while ((line = in.readLine()) != null) {
				sb.append(line);
			}
			System.out.println(sb.toString());
			in.close();
			String all = sb.toString();
			String[] all_a = all.split("n");
			//先得到坐标
			for (int i = 0; i < all_a.length; i++) {
				String[] all_b = all_a[i].split("b");
				System.out.println();
				for (int j = 0; j < all_b.length; j++) {
					if (all_b[j].equals("0")) {
						arr[j][i] = false;
					} else
						arr[j][i] = true;
				}
			}
			int bei = beishu;
			int dis = 25;
			int old_num = -1;
			for (int j = 0; j < height && !isallstop; j++) {
				for (int i = 0; i <= weith && !isallstop; i++) {
					//一定要sleep,要不然其他线程画不了东西
					Thread.sleep(25);
					Random rm = new Random();
					Bitmap bitmap = null;
					int num = 0;
					if (type == 1) {
						num = rm.nextInt(heart_all.length - 1);
						bitmap = bitmapcache
								.getBitmap(heart_all[num], mContext);
					} else if (type == 2) {
						bitmap = bitmapcache.getBitmap(R.drawable.love,
								mContext);
					}
					int bw = bitmap.getWidth();
					int bh = bitmap.getHeight();
					if (i >= weith  && !isallstop) {
					

					synchronized (holder) {
						Canvas c = null;
						try {
							float xx = (float) i;
							float yy = (float) j;
							//不要轻易去锁定整个屏幕
							c = holder.lockCanvas(new Rect(startx + (int) xx
									* bei, starty + (int) yy * bei,
									startx + (int) xx * bei + dis, starty
											+ (int) yy * bei + dis));

							// c = holder.lockCanvas();
							Paint p = new Paint(); // 创建画笔
							p.setColor(Color.RED);
							//下面这段是保证双缓冲能都画上东西,从而不会闪烁
							if (i > 0 && !isallstop) {
								int xx_b = i - 1;
								int yy_b = j;
								if (arr[xx_b][yy_b]) {
									if (old_num != -1) {
										if (type == 1)
											c.drawBitmap(bitmapcache.getBitmap(
													heart_all[old_num],
													mContext), startx + xx_b
													* bei, starty + yy_b * bei,
													p);
										else if (type == 2) {
											c.drawBitmap(bitmapcache.getBitmap(
													R.drawable.love, mContext),
													startx + xx_b * bei, starty
															+ yy_b * bei, p);
										}
									}
								}
							}
							if (arr[i][j] && !isallstop) {
								c.drawBitmap(bitmap, startx + xx * bei, starty
										+ yy * bei, p);
							}
							old_num = num;
						} catch (Exception e) {
							e.printStackTrace();
						} finally {
							try{
								if (c != null){
								<span style="white-space:pre">	</span>holder.unlockCanvasAndPost(c);// 结束锁定画图,并提交改变。
								}
							}catch(Exception e){
								e.printStackTrace();
							}
						}
					}					
				}
			}

		} catch (Exception e) {
			e.printStackTrace();
		}

	}


第二种方法就是点阵字符集,我程序中,如果设置的字不是内定的那寥寥几个,就会用点阵字符,点阵字符分16*1624*2432*3248*48,我代码里有前三种,每种字体又分为黑体宋体楷体等几种,在经过每一种尝试后,我最终选择的24HZKS,代码里每一种都有代码,大家也可以对每种进行测试,如果只要适应一款分辨率的话,会有更好的适配字体,我这是为了适应大多数的分辨率选的这种。24*24的代码如下,

public class Font24 {
	private Context context;
	public Font24(Context context){
		this.context = context;
	}
	
    private final static int[] mask = {128, 64, 32, 16, 8, 4, 2, 1};
    private final static String ENCODE = "GB2312";
    private final static String ZK16 = "Hzk24s";
    
    private boolean[][] arr;
    int all_16_32 = 24;
    int all_2_4 = 3;
    int all_32_128 = 72;
    public boolean[][] drawString(String str){
    	  byte[] data = null;
          int[] code = null;
          int byteCount;//到点阵数据的第几个字节了
          int lCount;//控制列
          
          arr = new boolean[all_16_32][all_16_32]; // 插入的数组
          //g.setColor(color);
          for(int i = 0;i < str.length();i ++){
              if(str.charAt(i) < 0x80){//非中文
                  //g.drawString(str.substring(i,i+1),x+(i<<4),y,0);
                  continue;
              }
              code = getByteCode(str.substring(i,i+1));
              data = read(code[0],code[1]);
              byteCount = 0;
              for(int line = 0;line < all_16_32;line ++){
                  lCount = 0;
                  for(int k = 0;k < all_2_4;k ++){
                      for(int j = 0;j < 8;j ++){
                         // if((data[byteCount]&mask[j])==mask[j]){
                    	   if (((data[byteCount] >> (7 - j)) & 0x1) == 1) {
                    		   arr[line][lCount] = true;
                        	  System.out.print("@");                          
                          }else{
                        	  System.out.print(" ");
                        	  arr[line][lCount] = false;
                          }
                          lCount++;
                      }
                      byteCount ++;
                  }
                  System.out.println();
              }
          }
          return arr;
    }
         
    /**
     *读取文字信息
     *@param areaCode 区码
     *@param posCode 位码
     *@return 文字数据
     */
    protected byte[] read(int areaCode,int posCode){
        byte[] data = null;
        try{
            int area = areaCode-0xa0;//获得真实区码
            int pos  = posCode-0xa0;//获得真实位码
            
            //InputStream in = getClass().getResourceAsStream(ZK32);
            InputStream in = Util.init().getAssetsInputStream(context, ZK16);
            long offset = all_32_128*((area-1)*94+pos-1);
            in.skip(offset);
            data = new byte[all_32_128];
            in.read(data,0,all_32_128);
            in.close();
        }catch(Exception ex){
        }
        return data;
    }
    
    /**
     *获得文字的区位码
     *@param str
     *@return int[2]
     */
    protected int[] getByteCode(String str){
        int[] byteCode = new int[2];
        try{
            byte[] data = str.getBytes(ENCODE);
            byteCode[0] = data[0] < 0?256+data[0]:data[0];
            byteCode[1] = data[1] < 0?256+data[1]:data[1];
        }catch(Exception ex){
        	ex.printStackTrace();
        }
        return byteCode;
    }
    
}


这段代码可以得到字体的坐标,1632的就是

int all_16_32 = 24;
int all_2_4 = 3;
int all_32_128 = 72;

三个参数不一样而己。

用坐标系画字大体差不多,代码如下

/**
	 * 16/24/32,要写的字符,开始的x,y,倍数,花或爱心
	 * @param font_kind
	 * @param s
	 * @param stx
	 * @param sty
	 * @param beishu
	 * @param type
	 */
	public void show_font16_24_32(int font_kind,String s, int stx, int sty, 
			int beishu, int type) {
		boolean[][] arr = null;
		int weith = 16;
		int height = 16;
		if(font_kind == 16){
			weith = 16;
			height = 16;
			arr = new boolean[weith][height];
			Font16 font16 = new Font16(mContext);
			arr = font16.drawString(s);
		}else if(font_kind == 24){
			weith = 24;
			height = 24;
			arr = new boolean[weith][height];
			Font24 font24 = new Font24(mContext);
			arr = font24.drawString(s);
		}else {
			weith = 32;
			height = 32;
			arr = new boolean[weith][height];
			Font32 font32 = new Font32(mContext);
			arr = font32.drawString(s);
		}
				
		int startx = stx, starty = sty;		
		int bei = beishu;
		int old_num = -1;
		int lCount;// 控制列
		for (int i = 0; i < weith && !isallstop; i++) {
			for (int j = 0; j < height && !isallstop; j++) {
				try {
					Thread.sleep(25);
				} catch (InterruptedException e1) {
					// TODO 自动生成的 catch 块
					e1.printStackTrace();
				}
				float xx = (float) j;
				float yy = (float) i;
				if (arr[i][j] && !isallstop) {

					Random rm = new Random();
					Bitmap bitmap = null;
					int num = 0;
					if (type == 1) {
						num = rm.nextInt(heart_all.length - 1);
						bitmap = bitmapcache
								.getBitmap(heart_all[num], mContext);
					} else if (type == 2) {
						bitmap = bitmapcache.getBitmap(R.drawable.love,
								mContext);
					}
					int bw = bitmap.getWidth();
					int bh = bitmap.getHeight();
					synchronized (holder) {
						Canvas c = null;
						try {

							// 不要轻易去锁定整个屏幕
							c = holder.lockCanvas(new Rect(startx + (int) xx
									* bei, starty + (int) yy * bei, startx
									+ (int) xx * bei + bw, starty + (int) yy
									* bei + bh));

							// c = holder.lockCanvas();
							Paint p = new Paint(); // 创建画笔
							p.setColor(Color.RED);
							// 下面这段是保证双缓冲能都画上东西,从而不会闪烁

							c.drawBitmap(bitmap, startx + xx * bei, starty + yy
									* bei, p);

							old_num = num;
						} catch (Exception e) {
							e.printStackTrace();
						} finally {
							try{
								if (c != null){
									holder.unlockCanvasAndPost(c);// 结束锁定画图,并提交改变。
								}
							}catch(Exception e){
								e.printStackTrace();
							}
						}
					}
				}


画出爱心,最主要得到爱心的坐标就可以了,具体可参照:http://love.hackerzhou.me/ 

private void run_hua_heart() {
			// TODO 自动生成的方法存根
			int startx = sw / 2 - 16, starty = sh / 2 - 68;
			int maxh = 100;  
			int y_dao = starty;
			double begin = 10; // 起始位置
			Random rm = new Random();
			int old_num = -1;
			float old_xx = 0, old_yy = 0;
			for (int i = 0; i < maxh  && !isallstop; i++) {
				try {
					Thread.sleep(80);
				} catch (InterruptedException e1) {
					// TODO 自动生成的 catch 块
					e1.printStackTrace();
				}

				int hua_num = rm.nextInt(18);
				Bitmap bit = bitmapcache
						.getBitmap(heart_all[hua_num], mContext);
				begin = begin + 0.2;  //密度
				double b = begin / Math.PI;
				double a = 13.5 * (16 * Math.pow(Math.sin(b), 3));  //这里的13.5可以控制大小
				double d = -13.5
						* (13 * Math.cos(b) - 5 * Math.cos(2 * b) - 2
								* Math.cos(3 * b) - Math.cos(4 * b));
				synchronized (holder) {
					Canvas c = null;
					try {
						float xx = (float) a;
						float yy = (float) d;

						c = holder.lockCanvas(new Rect(
								(int) (startx + xx - 40),
								(int) (starty + yy - 40),
								(int) (startx + xx + 40),
								(int) (starty + yy + 40)));
						Paint p = new Paint(); // 创建画笔
						p.setColor(Color.RED);
						//画上一个,要不然会闪烁
						if (old_num != -1) {
							Bitmap bb = bitmapcache.getBitmap(
									heart_all[old_num], mContext);
							c.drawBitmap(bb, startx + old_xx, starty + old_yy,
									p);
						}
						c.drawBitmap(bit, startx + xx, starty + yy, p);
						old_num = hua_num;
						old_xx = xx;
						old_yy = yy;
						// c.drawPoint(startx+xx,starty+yy, p);
					} catch (Exception e) {
						e.printStackTrace();
					} finally {
						try{
							if (c != null){
								holder.unlockCanvasAndPost(c);// 结束锁定画图,并提交改变。
							}
						}catch(Exception e){
							e.printStackTrace();
						}
					}
				}

第一界面就差不多了,一些花边就没必要说了。

第二个界面,要说的也不多,那个一点点画出来的大的爱心是从PC端上移植过去的,但我感觉那个爱心不太圆满,也没时间去修正了,但要注意的是画这个爱心的时候容易发生闪烁,我还是把代码贴出来吧,

public void run_heart() {
			int i, j;
			double x, y, r;
			int max = 180;
			//先计算出所有的位置,再去画图
			float[][] x_ff = new float[max][max];
			float[][] y_ff = new float[max][max];
			for (i = 0; i < max; i++) {
				for (j = 0; j < max; j++) {
					double pi = Math.PI;
					r = (pi / 45 * i * (1 - (Math.sin(pi / 45 * j))) * 18);
					x = ((r * (Math.cos(pi / 45 * j)) * (Math.sin(pi / 45 * i)) + w / 2) * 1.01);
					y = ((-r * (Math.sin(pi / 45 * j)) + h / 4) * 1.01);
					x_ff[i][j] = (float) x;
					y_ff[i][j] = (float) y;
				}
			}

			i = 0;
			j = 0;
			for (i = 0; i < max && !isallstop; i++) {

//					//sleep,屏幕
					try {
						Thread.sleep(10);
//						clearAll();
					} catch (InterruptedException e) {
//						// TODO 自动生成的 catch 块
						e.printStackTrace();
					}
					Canvas c = null;
					int numm = 10;
					
					for (j = 0; j < max && !isallstop; j=j+numm) {
						
						synchronized (holder) {
						try {
							Paint p = new Paint(); // 创建画笔
							p.setColor(Color.RED);
							//找出最大最小
							float xx_min=x_ff[i][j],
									xx_max=x_ff[i][j],
									yy_min=y_ff[i][j],
									yy_max=y_ff[i][j];
							for(int k =0;k<numm;k++){
								float xx_n = x_ff[i][j+k];
								float yy_n = y_ff[i][j+k];
								if(xx_n >= xx_max) xx_max = xx_n;
								if(xx_n <= xx_min) xx_min = xx_n;
								if(yy_n >= yy_max) yy_max = yy_n;
								if(yy_n <= yy_min) yy_min = yy_n;
										
							}
							int xmin,xmax,ymin,ymax;
							if(xx_min == 0) xmin = 0;
							else xmin = (int) (xx_min-5>0?xx_min-5:0);
							if(yy_min == 0) ymin = 0;
							else ymin = (int) (yy_min-5>0?yy_min-5:0);
							xmax = (int) (xx_max+5);
							ymax = (int) (yy_max+5);
							
						
							//c = holder.lockCanvas(new Rect(xi,yi,xa,ya));
							c = holder.lockCanvas(new Rect(xmin,ymin,xmax,ymax));
							
							if(j!=0){
								int m = j-numm;
								for(int k =0;k<numm;k++){
									float xx_n = x_ff[i][m+k];
									float yy_n = y_ff[i][m+k];
									c.drawPoint(xx_n, yy_n, p);
								}
							}
							for(int k =0;k<numm;k++){
								float xx_n = x_ff[i][j+k];
								float yy_n = y_ff[i][j+k];
								c.drawPoint(xx_n, yy_n, p);
							}

						} catch (Exception e) {
							e.printStackTrace();
						} finally {
							try{
								if (c != null){
									holder.unlockCanvasAndPost(c);// 结束锁定画图,并提交改变。
								}
							}catch(Exception e){
								e.printStackTrace();
							}
						}
						}
				}
			}
		}


第三个界面,如果有几张仙女连贯的动态图就好了,可惜我不是美工,尽管这整套都是我自己设计实现的,但不是美工无法设计出仙女散爱心的连续图,于是只能是晃啊晃啊然后爱心下落,下落后可以漂往左边或右边,并程抛物线飞行。

爱心变大,星星闪烁,花朵移动都在一个线程里:

public void show(){
			int ii = 30;
			boolean run = true;
			Paint p = new Paint();
			
			//旋转的花
			Bitmap hua = bitmapcache.getBitmap(R.drawable.hua, mContext);
			int huax = dest_x-40+xadd/2;
			int huay = 30;
			int huaw = hua.getWidth();
			int huah = hua.getHeight();
			int huamax = 180;
			int huamin = 0;
			int hua_add_plus = 2;
			int huar=0;	
			int re_num = 0;
			
			//星
			Bitmap xin1 = bitmapcache.getBitmapByLM(R.drawable.xin1, mContext,2);
			Bitmap xin2 = bitmapcache.getBitmapByLM(R.drawable.xin2, mContext,2);
			int xin1w = xin1.getWidth();
			int xin1h = xin1.getHeight();
			int xin2w = xin2.getWidth();
			int xin2h = xin2.getHeight();
			//三个星1,三个星2
			ArrayList<LoveDot> xinall = new ArrayList<LoveDot>();
			xinall.add(new LoveDot(1+xadd,10,1));
			xinall.add(new LoveDot(48+xadd,18,1));
			xinall.add(new LoveDot(110+xadd,40,1));
			xinall.add(new LoveDot(20+xadd,150,2));
			xinall.add(new LoveDot(150+xadd,160,2));
			xinall.add(new LoveDot(130+xadd,190,2));
			
			boolean xinboolean = true;  //为真的时候画星,为假的时候擦除
			int oldx = 0;
			while (true  && !isallstop) {
				try {
					Thread.sleep(150);
				} catch (InterruptedException e2) {
					// TODO 自动生成的 catch 块
					e2.printStackTrace();
				}
				
				//旋转加透明
				synchronized (holder) {
					Canvas c = null;
					Bitmap b2 = null;	
					try {
						//c.drawColor(co);					
						Matrix m = new Matrix();
						m.setRotate(huar);
						p.setAlpha(255-Math.abs(huar));
						b2 = Bitmap.createBitmap(
									hua, 0, 0, huaw,huah, m, true);	
						c = holder.lockCanvas(new Rect(huax,huay,huax+b2.getWidth(),
								huay+b2.getHeight()));
						c.drawColor(Color.TRANSPARENT,Mode.CLEAR);
						c.drawBitmap(b2, huax,huay, p);
						//c.drawBitmap(big, dest_x, dest_y, p);
						
						huar = huar+hua_add_plus;
						if(huar==huamax) hua_add_plus = -2;
						if(huar == huamin) hua_add_plus = 2;
						
					} catch (Exception e) {
						e.printStackTrace();
					} finally {
						try{
							if (c != null){
								holder.unlockCanvasAndPost(c);// 结束锁定画图,并提交改变。
							}
						}catch(Exception e){
							e.printStackTrace();
						}
						//if(b2 != null)
						//	b2.recycle();
					}
				}
				
				
				//星星闪烁
				//为真的时候画星,为假的时候擦除
				if(xinboolean){
					
					LoveDot d = xinall.get(oldx);
					Bitmap xinb = null;
					int xw,xh;
					int xx = d.x;
					int yy = d.y;
					if(d.num == 2){
						xinb = xin2;
						xw = xin2w;
						xh = xin2h;
					}
					else {
						xinb = xin1;
						xw = xin1w;
						xh = xin1h;
					}
					
					synchronized (holder) {
						Canvas c = null;
						try {
							c = holder.lockCanvas(new Rect(xx,yy,xx+xw,yy+xh));							
							p.setAlpha(255);
							//c.drawColor(Color.TRANSPARENT,Mode.CLEAR);
							c.drawBitmap(xinb, xx,yy, p);
						
						} catch (Exception e) {
							e.printStackTrace();
						} finally {
							try{
								if (c != null){
									holder.unlockCanvasAndPost(c);// 结束锁定画图,并提交改变。
								}
							}catch(Exception e){
								e.printStackTrace();
							}
						}

					}
					//oldx = thisone;
					xinboolean = !xinboolean;
				}else{
					int thisone = getRandom(0, xinall.size()-1);
					LoveDot d = xinall.get(thisone);
					int xw,xh;
					int xx = d.x;
					int yy = d.y;
					if(d.num == 2){
						//xinb = xin2;
						xw = xin2w;
						xh = xin2h;
					}
					else {
						//xinb = xin1;
						xw = xin1w;
						xh = xin1h;
					}
					synchronized (holder) {
						Canvas c = null;
						try {
							c = holder.lockCanvas(new Rect(xx,yy,xx+xw,yy+xh));							
							p.setAlpha(255);
							c.drawColor(Color.TRANSPARENT,Mode.CLEAR);						
						} catch (Exception e) {
							e.printStackTrace();
						} finally {
							try{
								if (c != null){
									holder.unlockCanvasAndPost(c);// 结束锁定画图,并提交改变。
								}
							}catch(Exception e){
								e.printStackTrace();
							}
						}

					}
					oldx = thisone;
					xinboolean = !xinboolean;
				}
												
				re_num++;
				if(re_num>3){
					re_num = 0;
				}else continue;
				
				Bitmap big15 = bitmapcache.getBitmap(R.drawable.big99, mContext);
				//Y为dest ,x 为dest - w/2
				int bw = big15.getWidth();
				int bh = big15.getHeight();
				Bitmap mBitmap = Bitmap.createScaledBitmap(big15, bw-ii, bh-ii, true);  
				bw = mBitmap.getWidth();
				bh = mBitmap.getHeight();
				int x = dest_x-bw/2;
				int y = dest_y;
				//
				dropx = x;
				dropy = y;
				//dropw = ,droph
				synchronized (holder) {
					Canvas c = null;
					try {
						c = holder.lockCanvas(new Rect(x-1,y-1,x+1+bw,y+1+bh));					
						p.setAlpha(255);
						c.drawColor(Color.TRANSPARENT,Mode.CLEAR);
						c.drawBitmap(mBitmap, x,y, p);
						//c.drawBitmap(big, dest_x, dest_y, p);
					} catch (Exception e) {
						e.printStackTrace();
					} finally {
						try{
							if (c != null){
								holder.unlockCanvasAndPost(c);// 结束锁定画图,并提交改变。
							}
						}catch(Exception e){
							e.printStackTrace();
						}
					}

				}
				ii--;
				if(ii <=0) {
					try {
						Thread.sleep(500);
					} catch (InterruptedException e1) {
						// TODO 自动生成的 catch 块
						e1.printStackTrace();
					}
					ii = 30;

					synchronized (holder) {
						Canvas c = null;
						try {
							c = holder.lockCanvas(new Rect(x-1,y-1,x+1+bw,y+1+bh));
							//c.drawColor(co);
							c.drawColor(Color.TRANSPARENT,Mode.CLEAR);
							//c.drawBitmap(big15, x,y, p);
							//c.drawBitmap(big, dest_x, dest_y, p);
						} catch (Exception e) {
							e.printStackTrace();
						} finally {
							try{
								if (c != null){
									holder.unlockCanvasAndPost(c);// 结束锁定画图,并提交改变。
								}
							}catch(Exception e){
								e.printStackTrace();
							}
						}

					}
					if(!isallstop){
						dropnum++;
						Thread drop = new LoveDrop(dropnum,x,y);
						drop.start();
						dropthread_Add(dropnum, drop);
						//new LoveDrop(x,y).start();
					}
							
					try {
						Thread.sleep(1500);
					} catch (InterruptedException e1) {
						// TODO 自动生成的 catch 块
						e1.printStackTrace();
					}
				}
			}
		}
<span style="font-size:14px;">下落的代码如下</span>
private void drop(){
			//startx = dest_x;
			//starty = dest_y+10;
			endy = h-100;  //最多下落到这
			endx = startx;
			Bitmap llove = bitmapcache.getBitmap(R.drawable.big_h, mContext);
			int bw = llove.getWidth();
			int bh = llove.getHeight();
			Paint p = new Paint();
			boolean isr = true;
			long de = 60;
			dropw = bw+1;
			droph = bh+1;
			while(isr && !isallstop){
				synchronized (holder) {
					Canvas c = null;
					try {
						//Xfermode xFermode = new PorterDuffXfermode(Mode.DST_ATOP);
						//p.setXfermode(xFermode);
						c = holder.lockCanvas(new Rect(startx,starty-2,startx+bw,starty+bh+1));						
						c.drawColor(Color.TRANSPARENT,Mode.CLEAR);
						c.drawBitmap(llove, startx,starty++, p);						
					} catch (Exception e) {
						e.printStackTrace();
					} finally {
						try{
							if (c != null){
								holder.unlockCanvasAndPost(c);// 结束锁定画图,并提交改变。
							}
						}catch(Exception e){
							e.printStackTrace();
						}
					}

				}
				try {
					Thread.sleep(de);
				} catch (InterruptedException e) {
					// TODO 自动生成的 catch 块
					e.printStackTrace();
				}
				de=(long) (de-0.05);
				if(de <=40) de=(long) (de-0.01);
				if(de <=20) de = 20;
				if(starty >= endy && !isallstop){//准备往左右
					isr = false;  //结束线程
					 // 初始化y轴数据					
					int centerY = endy;
					//int[] Y_axis = new int[w-startx];
					int left_right = getRandom(0, 10);
					boolean isright = true;  //为真为右,为假为左,为右的机会大些
					if(left_right<4){  //左
						isright = false;
					}
					int le,top;
					
					int maxhh = endy - maxziy;
					int rmin = 80,rmax = 100;
					int lmin = 40,lmax = 50;
					if(maxhh <100 && maxhh>50 ) {
						rmin = 50;
						rmax = 60;
					}
					if(maxhh < 50){
						rmin = 30;
						rmax = 40;
						lmin = 20;
						lmax = 30;
					}
					
					if(isright){
						le = w-startx;
						top = getRandom(rmin, rmax);
					}
					else {
						le = startx+bw;
						top = getRandom(lmin,lmax);
					}
					for (int i = 1; i < le && !isallstop; i++) {// 计算正弦波
						int x;
						if(isright)
							x = startx+i;
						else x = startx-i;
						//y=Asin(ωx+φ φ(初相位):决定波形与X轴位置关系或横向移动距离(左加右减)
						//ω:决定周期(最小正周期T=2π/|ω|)
						//		A:决定峰值(即纵向拉伸压缩的倍数) 	
						int y = centerY-Math.abs( (int) (top * Math.sin(i * 2 * Math.PI/ 180)));
						synchronized (holder) {
							Canvas c = null;
							try {
								c = holder.lockCanvas(new Rect(x-2,
										y-15, x + bw+1, y + bh
												+ 15));								
								c.drawColor(Color.TRANSPARENT, Mode.CLEAR);
								c.drawBitmap(llove, x, y, p);								
							} catch (Exception e) {
								e.printStackTrace();
							} finally {
								try{
									if (c != null){
										holder.unlockCanvasAndPost(c);// 结束锁定画图,并提交改变。
									}
								}catch(Exception e){
									e.printStackTrace();
								}
							}

						}// sy
						int delay = endy - y;
						try {
							//顶峰慢,delay 大,越慢,时间长
							Thread.sleep(50+delay*2);
							//System.out.println("y:"+y);
						} catch (InterruptedException e) {
							// TODO 自动生成的 catch 块
							e.printStackTrace();
						}
					}	
				}
			}
		}


至于字的显现,应该没什么好说,值得注意的是,还有一些闪烁的爱心和下缀的那一段,要注意这些坐标,不能覆盖字,要处理所有出现的心的坐标,和字的坐标。

另外,还有播放声音的功能,可以自己设置合适的音乐或者自己录好自己想说的话然后播放出来。

源码还在不断修改更新中,随意拿去自用。




© 著作权归作者所有

w
粉丝 2
博文 1
码字总数 4111
作品 0
长沙
私信 提问
加载中

评论(2)

千里山南
千里山南
这个可以使用libgdx来做,会方便些
红薯
红薯
把代码放到 git.oschina.net ,访问更快:)
用算法撩妹都不会,别跟我说你是程序员

  程序员浪漫的表白方式可以说是花样百出,为什么用在自己身上就没效果呢?   作为一个程序员“身边的女生”,小编觉得,大部分程序员没有女朋友,很可能是恋爱技能bug太多,当你还不确定...

超级数学建模
2018/02/02
0
0
七夕特辑 不会表白的程序员,就继续凭本事单身吧(送惊喜FreeBuf大礼包)

     不好意思,来的有些晚了,不过只要是对的人,每一天都是七夕。      根据FreeBuf 不知道可不可靠的数据统计,程序员中单身比例已经超过50%,男女比例12:1,基本都位于各行业顶端...

FreeBuf
2018/08/17
0
0
漫画:程序员的“情人”节应该这样度过

今天是2018年8月17号,一年一度的情人节又来了,今天对于很多年轻人来说是个特别的日子。但是作为屌丝界的一枚程序员,往往给人的印象是宅,不爱说话,智商不好,也不讨好哄女孩子欢心。但是...

codeGoogle
2018/08/17
0
0
C语言七夕必备神器,待那烟花灿烂时,依旧做个单身狗

C/C++程序员告诉你什么叫浪漫,表白黑科技,炫酷多彩求爱利器 前言 缘是美丽的邂逅,爱是心跳的感觉,情是心灵的交会,恋是甜蜜的思念,走在爱与被爱的边缘,你见或者不见,爱你的心始终不改...

C语言学习
2018/08/17
0
0
这些开源项目让程序员们完美度过"双11"

关爱“剁手族”和“单身狗”的“双11”终于来啦,每年这个时候总是有人欢喜有人愁,对于程序员来说,就应该用程序员特有的方式来度过这个特殊的日子~ 无论你是依然沉浸在自己的代码里▼ 还是...

两味真火
2016/11/10
6.4K
9

没有更多内容

加载失败,请刷新页面

加载更多

分布式协调服务zookeeper

ps.本文为《从Paxos到Zookeeper 分布式一致性原理与实践》笔记之一 ZooKeeper ZooKeeper曾是Apache Hadoop的一个子项目,是一个典型的分布式数据一致性的解决方案,分布式应用程序可以基于它...

ls_cherish
今天
4
0
redis 学习2

网站 启动 服务端 启动redis 服务端 在redis 安装目录下 src 里面 ./redis-server & 可以指定 配置文件或者端口 客户端 在 redis 的安装目录里面的 src 里面 ./redis-cli 可以指定 指定 连接...

之渊
昨天
2
0
Spring boot 静态资源访问

0. 两个配置 spring.mvc.static-path-patternspring.resources.static-locations 1. application中需要先行的两个配置项 1.1 spring.mvc.static-path-pattern 这个配置项是告诉springboo......

moon888
昨天
4
0
hash slot(虚拟桶)

在分布式集群中,如何保证相同请求落到相同的机器上,并且后面的集群机器可以尽可能的均分请求,并且当扩容或down机的情况下能对原有集群影响最小。 round robin算法:是把数据mod后直接映射...

李朝强
昨天
4
0
Kafka 原理和实战

本文首发于 vivo互联网技术 微信公众号 https://mp.weixin.qq.com/s/bV8AhqAjQp4a_iXRfobkCQ 作者简介:郑志彬,毕业于华南理工大学计算机科学与技术(双语班)。先后从事过电子商务、开放平...

vivo互联网技术
昨天
24
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部